Javascript 有趣的递归lambda示例

Javascript 有趣的递归lambda示例,javascript,python,lambda,semantics,Javascript,Python,Lambda,Semantics,我只是偶然发现了一个递归lambdas的有趣示例,我真的不明白它为什么以这种方式工作 rec = lambda x : 1 if x==0 else rec(x-1)*x f = rec rec = lambda x: x+1 print(f(10)) 在javascript中也是如此 var rec=功能{ 如果a==0,则返回1; 返回reca-1*a; } var f=rec rec=功能{ 返回a+1; } console.logf10 这3条语句可以归结为一条语句 rec =

我只是偶然发现了一个递归lambdas的有趣示例,我真的不明白它为什么以这种方式工作

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
print(f(10))  
在javascript中也是如此

var rec=功能{ 如果a==0,则返回1; 返回reca-1*a; } var f=rec rec=功能{ 返回a+1; }
console.logf10 这3条语句可以归结为一条语句

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
从1号到2号

f = lambda x : 1 if x==0 else rec(x-1)*x
从上面&3

f = lambda x : 1 if x==0 else x*x

这3条语句可以归结为一条语句

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
从1号到2号

f = lambda x : 1 if x==0 else rec(x-1)*x
从上面&3

f = lambda x : 1 if x==0 else x*x
您可以添加一些console.log和view,首先用10调用f,然后用9调用rec,结果是10*10

var rec=功能{ 控制台。日志'f',a; 如果a==0,则返回1; 返回reca-1*a; }; f=rec; rec=功能{ console.log'rec',a; 返回a+1; } console.logf10 您可以添加一些console.log和view,首先用10调用f,然后用9调用rec,结果是10*10

RECVAR=功能{ 控制台。日志'f',a; 如果a==0,则返回1; 返回reca-1*a; }; f=rec; rec=功能{ console.log'rec',a; 返回a+1; }
console.logf10 我建议正确使用变量名,这里不需要重新分配

为什么它使用第二个rec而不是第一个rec

您的函数调用是在重新分配rec之后发生的,因此您将rec中的最新值作为

rec = function(a) {
  return a + 1;
}
var f=函数{ 如果a==0,则返回1; 返回reca-1*a; } var rec=功能{ 返回a+1; }
console.logf10 我建议正确使用变量名,这里不需要重新分配

为什么它使用第二个rec而不是第一个rec

您的函数调用是在重新分配rec之后发生的,因此您将rec中的最新值作为

rec = function(a) {
  return a + 1;
}
var f=函数{ 如果a==0,则返回1; 返回reca-1*a; } var rec=功能{ 返回a+1; }
console.logf10 我将针对python进行讨论,因为这是我所熟悉的

首先,这种行为是可能的,因为我认为python和javascript的闭包遵循后期绑定

后期绑定是在运行时查找闭包中的名称,而早期绑定是在编译时查找名称

这允许在运行时改变行为,方法是将在运行时查找的变量重新绑定为rec之类的函数

最后一步就是将lambda函数转换成等价的def语法,这样真正的行为就更清晰了

守则:

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
print(f(10)) 
可等同于:

第一:

def somefunc(x):
    return 1 if x==0 else rec(x-1)*x 
注意,python不会抱怨rec即使在干净的会话/内核上也不存在,因为它在函数定义期间不会查找该值。后期绑定意味着除非调用此函数,否则python不关心rec是什么

然后:

现在我们更改rec函数

并观察f的后续函数调用将使用后期绑定rec,即在函数调用中查找的rec

f(10) #100
PS.在下面添加完整代码:

def somefunc(x):
    return 1 if x==0 else rec(x-1)*x

rec = somefunc

f = rec

def someotherfunc(x):
    return x + 1

f(10) #3628800

rec = someotherfunc

f(10) #100

我将针对python进行讨论,因为这是我所熟悉的

首先,这种行为是可能的,因为我认为python和javascript的闭包遵循后期绑定

后期绑定是在运行时查找闭包中的名称,而早期绑定是在编译时查找名称

这允许在运行时改变行为,方法是将在运行时查找的变量重新绑定为rec之类的函数

最后一步就是将lambda函数转换成等价的def语法,这样真正的行为就更清晰了

守则:

rec = lambda x : 1 if x==0 else rec(x-1)*x
f = rec 
rec = lambda x: x+1
print(f(10)) 
可等同于:

第一:

def somefunc(x):
    return 1 if x==0 else rec(x-1)*x 
注意,python不会抱怨rec即使在干净的会话/内核上也不存在,因为它在函数定义期间不会查找该值。后期绑定意味着除非调用此函数,否则python不关心rec是什么

然后:

现在我们更改rec函数

并观察f的后续函数调用将使用后期绑定rec,即在函数调用中查找的rec

f(10) #100
PS.在下面添加完整代码:

def somefunc(x):
    return 1 if x==0 else rec(x-1)*x

rec = somefunc

f = rec

def someotherfunc(x):
    return x + 1

f(10) #3628800

rec = someotherfunc

f(10) #100

通过以这种方式使用变量名,您将使其变得复杂,您不需要在此处重新赋值REC是一个变量。当在f引用的函数中调用它时,它使用的是当前值,而不是最初定义时的值。这不是一个递归场景。以这种方式使用变量名会使它变得复杂,您不需要在此处重新赋值REC是一个变量。当在f引用的函数中调用它时,它使用的是当前值,而不是最初定义时的值。这不是一个递归的场景。是的,我知道它怎么能打印出100。但是为什么我不明白为什么第二个rec被调用而不是第一个?因为它有一个新的内容。保存
引用旧函数时,需要一个带rec的命名函数,然后任何递归调用都使用此引用{当第一次调用原始rec时,第二次调用仍然绑定到新定义的函数。那么为什么赋值在这里有帮助呢?这不是我的赋值。我在帖子中做了一个编辑来详细说明这个问题。是的,我理解它如何打印100。但是为什么我不理解为什么第二次调用rec而不是第一个?因为它有一个新的内容。为了保留对旧函数的引用,您需要一个带rec的命名函数,然后任何递归调用都会使用此引用。因此,如果您将var rec=function reca{行更改为function reca{{第二次调用仍然绑定到新定义的函数,而第一次调用原始rec。那么为什么赋值在这里有用呢?这不是我的赋值。我在帖子中做了一个编辑来详细说明这个问题