JavaScript箭头功能和关闭问题

时间:2018-10-19 15:18:10

标签: javascript closures arrow-functions

我正在使用Javascript处理Lambda表达式,并编写了以下代码:

var succRender = (x) => 'succ('+ x + ')';
var numerify = expr => ((expr)(succRender) (0));
var ZERO = f => x => (x) ;
var ONE  = f => x => (f(x)); 
var TWO = f => x => (f(f(x))); 
var THREE = f => x => (f(f(f(x))));
var PLUS = n => m => f => z => (n(f) (m(f)(z))) ;

当我打电话时:

console.log(numerify((PLUS) (TWO) (THREE)));

控制台正确答复

succ(succ(succ(succ(succ(0)))))

但是我打电话给了

console.log(numerify((PLUS) (TWO) (THREE)));

var PLUS = n => m => f => z => (n(f) (m(f)(z))) ;

具有四个参数... Javascript如何真正发挥这种作用?通话中f和z的“值”是什么?而Javascript如何检索那些值二来完成任务呢?

预先感谢

Ed

2 个答案:

答案 0 :(得分:0)

让我们逐步评估它:

  PLUS(TWO)

调用第一个函数并以TWO的形式传递n,其结果为:

 m => f => z => (n(f) (m(f)(z)))

然后用(THREE)进行调用,因此mTHREE,其计算结果为:

 f => z => (n(f) (m(f)(z)))

现在numerify(...)被调用,其中expr在上一行,并且在函数内部是:

 expr(succRender)(0)

因此它以fsuccRenderz0的方式调用函数。现在我们可以评估PLUS主体,因此:

  n(f) (m(f)(z))

成为:

  TWO(succRender) (THREE(succRender)(0))

现在对TWO调用进行评估,其中succRenderf,上面的行结果为

 (x => (f(f(x)))) (THREE(succRender)(0))

THREE也是如此:

 (x => f(f(x)))) ((x => (f(f(f(x)))))(0))

现在,当使用(0)调用ut时,将评估右箭头函数,因此x0

 (x => f(f(x))) (f(f(f(0))))

因此,现在succRenderf)被调用了三次,而前一次调用是重复的:

 (x => f(f(x))) ("succ(succ(succ(0)))")

现在,最后一个箭头函数得到求值,succRender又被调用两次:

 "succ(succ(succ(succ(succ(0)))))"

答案 1 :(得分:0)

让我们稍微整理一下包装,以更清楚地了解正在发生的事情。我已经将PLUS重新编写为一个更简单的函数,该函数仍然需要四个参数,只是将它们加在一起。

var PLUS = a => b => c => d => a + b + c + d;

var intermediateResult = (PLUS)(1)(2); //the parenthesis around PLUS are actually not needed
console.log("intermediateResult", intermediateResult);

var secondIntermediateResult = intermediateResult(3);
console.log("secondIntermediateResult", secondIntermediateResult);

var finalResult = intermediateResult(3)(4);
console.log("finalResult", finalResult);

如您所见,如果仅传递前两个参数,则会返回一个函数。您需要“填写”所有值才能获得结果。


现在,让我们来分解一下代码中发生的事情:

(PLUS) (TWO) (THREE)

正如我所提到的,PLUS周围不需要括号。他们什么也没做。所以我将重写这里发生的事情:

var firstIntermediateResult = PLUS(TWO);
var secondIntermediateResult = firstIntermediateResult(THREE);

因此,您要传递前两个参数。

numerify((PLUS) (TWO) (THREE))

如果我们用之前的细分代替,则等同于

numerify(secondIntermediateResult)

因此,让我们看一下numerify函数:

var numerify = expr => ((expr)(succRender) (0));

它接受一个名为expr的参数,然后将succRender传递给它。这是另一个功能,但是在理解调用顺序方面并不重要。从上面我们可以看到,它将返回另一个函数,该函数在返回结果之前需要有一个最终参数,并且该参数为0,因此,将程序的结果重写为:

var thirdIntermediateResult = secondIntermediateResult(succRender);
var finalResult = thirdIntermediateResult(0);

因此,提供所有参数后的PLUS的最终形式如下

n(f) (m(f)(z)) --> TWO(succRender)(THREE(succRender)(0))