Functional programming 什么是';关闭';?
我问了一个关于咖喱和闭馆的问题。 什么是结束?它与咖喱有什么关系?我将举一个例子(用JavaScript): 这个函数makeCounter的作用是返回一个函数,我们称之为x,每次调用该函数时,该函数的计数都是1。因为我们没有向x提供任何参数,所以它必须以某种方式记住计数。它知道在什么地方可以找到它,这是基于所谓的词法范围-它必须寻找定义它的地方才能找到值。这个“隐藏”值就是所谓的闭包Functional programming 什么是';关闭';?,functional-programming,computer-science,terminology,glossary,Functional Programming,Computer Science,Terminology,Glossary,我问了一个关于咖喱和闭馆的问题。 什么是结束?它与咖喱有什么关系?我将举一个例子(用JavaScript): 这个函数makeCounter的作用是返回一个函数,我们称之为x,每次调用该函数时,该函数的计数都是1。因为我们没有向x提供任何参数,所以它必须以某种方式记住计数。它知道在什么地方可以找到它,这是基于所谓的词法范围-它必须寻找定义它的地方才能找到值。这个“隐藏”值就是所谓的闭包 (define x 3) (define (plus-x y) (+ x y)) (let ((x 5
(define x 3)
(define (plus-x y)
(+ x y))
(let ((x 5))
(plus-x 4)) returns 7
下面是我的咖喱例子:
function add (a) {
return function (b) {
return a + b;
}
}
var add3 = add(3);
add3(4); returns 7
您可以看到,当您使用参数a(即3)调用add时,该值包含在我们定义为add3的返回函数的闭包中。这样,当我们调用add3时,它知道在哪里找到a值来执行加法。闭包是一个可以引用另一个函数中状态的函数。例如,在Python中,它使用闭包“inner”:
def外部(a):
b=“外部变量()
def内部(c):
打印a、b、c
返回内部
#现在可以保存outer()的返回值以备以后使用
func=外部(“测试”)
func(1)#打印“外部()中的测试变量”
在正常情况下,变量受作用域规则的约束:局部变量仅在定义的函数内工作。为了方便起见,闭包是暂时打破此规则的一种方式
def n_times(a_thing)
return lambda{|n| a_thing * n}
end
在上面的代码中,lambda(|n | a|u thing*n}
是闭包,因为a_thing
由lambda(匿名函数创建者)引用
现在,如果将生成的匿名函数放入函数变量中
foo = n_times(4)
foo将打破正常的作用域规则,开始在内部使用4
foo.call(3)
返回12。非常好。我认为唯一需要澄清的是,闭包基本上是创建lambda函数时堆栈的快照。然后当函数重新执行时,堆栈在执行函数之前恢复到该状态。因此,正如Kyle提到的,隐藏值(
count
)在执行lambda函数时可用。为了帮助理解闭包,可能需要检查如何在过程语言中实现闭包。此解释将遵循Scheme中闭包的简化实现
首先,我必须介绍名称空间的概念。当您在Scheme解释器中输入命令时,它必须计算表达式中的各种符号并获得它们的值。示例:
(define x 3)
(define y 4)
(+ x y) returns 7
define表达式在spot中为x存储值3,在spot中为y存储值4。然后,当我们调用(+xy)时,解释器在名称空间中查找值,并且能够执行操作并返回7
但是,在Scheme中,有一些表达式允许您临时重写符号的值。以下是一个示例:
(define x 3)
(define y 4)
(let ((x 5))
(+ x y)) returns 9
x returns 3
let关键字所做的是引入一个新的名称空间,其中x的值为5。您会注意到,它仍然可以看到y是4,使总和返回为9。您还可以看到,一旦表达式结束,x将返回为3。从这个意义上说,x已被局部值暂时屏蔽
过程语言和面向对象语言有一个相似的概念。每当你在一个函数中声明一个与全局变量同名的变量,你就会得到同样的效果
我们将如何实现这一点?一种简单的方法是使用链表-头包含新值,尾包含旧名称空间。当需要查找符号时,从头开始,然后从尾开始
现在让我们跳到一级函数的实现。函数或多或少是一组在调用函数时执行的指令,以返回值为顶点。当我们读入函数时,我们可以在后台存储这些指令,并在调用函数时运行它们
(define x 3)
(define (plus-x y)
(+ x y))
(let ((x 5))
(plus-x 4)) returns ?
我们将x定义为3,将plus-x定义为它的参数y,加上x的值。最后,我们在一个环境中调用plus-x,其中x被一个新的x屏蔽,这个值为5。如果我们只存储操作,(+xy),对于函数plus-x,因为我们在x为5的上下文中,返回的结果将是9。这就是所谓的动态作用域
然而,Scheme、Common Lisp和许多其他语言都有所谓的词法作用域——除了存储操作(+x y)之外,我们还将名称空间存储在该特定点。这样,当我们查找值时,我们可以看到,在这个上下文中,x实际上是3。这是一个闭包
(define x 3)
(define (plus-x y)
(+ x y))
(let ((x 5))
(plus-x 4)) returns 7
总之,我们可以使用一个链表来存储函数定义时名称空间的状态,允许我们从封闭的作用域中访问变量,并使我们能够在不影响程序其余部分的情况下局部屏蔽变量。下面是一个实实在在的例子,说明了闭包为什么会起作用……这是straig这是我的Javascript代码的一部分。让我举例说明
Function.prototype.delay=函数(ms/*[,arg…]*/){
var fn=这个,
args=Array.prototype.slice.call(参数,1);
return window.setTimeout(函数(){
返回fn.apply(fn,args);
},ms);
};
下面是您将如何使用它:
var startPlayback=功能(轨道){
播放器。播放(曲目);
};
开始播放(someTrack);
现在想象一下,您希望延迟播放开始,例如,此代码段运行5秒后。这很容易使用delay
完成:
startPlayback.delay(5000,someTrack);
//继续,做其他事情
当您使用5000
ms调用delay
时,第一个代码段将运行,并将传入的参数存储在它的闭包中。然后5秒后,当setTimeout
回调发生时,闭包仍会保留这些参数
local old_dofile = dofile
function dofile( filename )
if filename == nil then
error( 'Can not use default of stdin.' )
end
old_dofile( filename )
end
var f=function(){
var a=7;
var g=function(){
return a;
}
return g;
}
{
global: 2,
w: "unused",
y: [whatever has been passed to that wrapper function as its parameter `y`]
}
{
y: [whatever has been passed to that wrapper function as its parameter `y`]
}
Listing 2-18:
function outerFunction(arg) {
var variableInOuterFunction = arg;
function bar() {
console.log(variableInOuterFunction); // Access a variable from the outer scope
}
// Call the local function to demonstrate that it has access to arg
bar();
}
outerFunction('hello closure!'); // logs hello closure!
for(var i=0; i< 5; i++){
setTimeout(function(){
console.log(i);
}, 1000);
}
for(var i=0; i< 5; i++){
(function(j){ //using IIFE
setTimeout(function(){
console.log(j);
},1000);
})(i);
}
(function(j){ //i is passed here
setTimeout(function(){
console.log(j);
},1000);
})(i); //look here it called immediate that is store i=0 for 1st loop, i=1 for 2nd loop, and so on and print 0,1,2,3,4
for(let i=0; i< 5; i++){
setTimeout(function(){
console.log(i);
},1000);
}
Output: 0,1,2,3,4
setTimeout(function(){
console.log(i);
},1000);
setTimeout(function(){
console.log(i);
},1000);
setTimeout(function(){
console.log(i);
},1000);
setTimeout(function(){
console.log(i);
},1000);
setTimeout(function(){
console.log(i);
},1000);
function multiply (x, y) {
return x * y;
}
const double = multiply.bind(null, 2);
const eight = double(4);
eight == 8;
function apple(x){
function google(y,z) {
console.log(x*y);
}
google(7,2);
}
apple(3);
// the answer here will be 21
function init() {
var name = “Mozilla”;
}
function init() {
var name = “Mozilla”;
function displayName(){
alert(name);
}
displayName();
}
var a = 0;
a = a + 1; // => 1
a = a + 1; // => 2
a = a + 1; // => 3
class Bread {
constructor (weight) {
this.weight = weight;
}
render () {
return `My weight is ${this.weight}!`;
}
}
var n = 0;
var count = function () {
n = n + 1;
return n;
};
count(); // # 1
count(); // # 2
count(); // # 3
var countGenerator = function () {
var n = 0;
var count = function () {
n = n + 1;
return n;
};
return count;
};
var count = countGenerator();
count(); // # 1
count(); // # 2
count(); // # 3
def outer() {
def x = 1
return { -> println(x)} // inner
}
def innerObj = outer()
innerObj() // prints 1
function makeAdder(x) {
return function(y) {return x + y;}
}
var add10 = makeAdder(10);
var add5 = makeAdder(5);
document.write(″add 10 to 20: ″ + add10(20) +
″<br />″);
document.write(″add 5 to 20: ″ + add5(20) +
″<br />″);
function sayHello() {
const greeting = "Hello World";
return function() { // anonymous function/nameless function
console.log(greeting)
}
}
const hello = sayHello(); // hello holds the returned function
hello(); // -> Hello World
; Function using a local variable
(define (function)
(define a 1)
(display a) ; prints 1, when calling (function)
)
(function) ; prints 1
(display a) ; fails: a undefined
; Function using a global variable
(define b 2)
(define (function)
(display b) ; prints 2, when calling (function)
)
(function) ; prints 2
(display 2) ; prints 2
; Function with closure
(define (outer)
(define c 3)
(define (inner)
(display c))
inner ; outer function returns the inner function as result
)
(define function (outer))
(function) ; prints 3