Functional programming 什么是';关闭';?

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

我问了一个关于咖喱和闭馆的问题。 什么是结束?它与咖喱有什么关系?

我将举一个例子(用JavaScript):

这个函数makeCounter的作用是返回一个函数,我们称之为x,每次调用该函数时,该函数的计数都是1。因为我们没有向x提供任何参数,所以它必须以某种方式记住计数。它知道在什么地方可以找到它,这是基于所谓的词法范围-它必须寻找定义它的地方才能找到值。这个“隐藏”值就是所谓的闭包

(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