[英]Why does wrapping a function with a lambda fix stack overflow?
如果expression求值是一個參數的函數,我會認為lambda x:( expression )(x)與expression相同-但實際上並非如此。 考慮Y組合器的以下兩個定義:
def Y1(F):
left = lambda x: x(x)
right = lambda x: F(x(x))
return left(right)
def Y2(F):
left = lambda x: x(x)
right = lambda x: lambda y: (F(x(x)))(y)
return left(right)
Y2實際上按預期工作,但是調用Y1會引起堆棧溢出。 為什么在行為上有這種差異?
不, lambda x: (expression)(x)
與expression
並不相同。
它是一個函數,在調用時將返回expression
的結果,而不同於立即返回其結果的expression
。
那是什么結果? 它是一個參數的函數。 但這還不存在。 它需要構造,計算。 這就是expression
作用。 它計算表示“下一個”遞歸調用的遞歸函數,該遞歸函數可能需要由Y組合器構造的遞歸函數來完成 。
Y1
試圖過早,過分急切地找到right
的值-它試圖在返回計算的遞歸函數之前執行此操作。 因此,它永遠不會返回,因為Y1
總是在返回前一個遞歸函數之前嘗試計算下一個遞歸函數,以便可以對其進行調用。
但Y2
構建遞歸函數, 將計算時,將需要它的下一個遞歸函數; 但還不是“現在”。 它將其構造為lambda函數,這會延遲實際計算。 lambda函數的構建是一個簡單的一步過程,該過程很快完成,然后返回計算出的遞歸函數,因此可以使用它,並且僅當/何時它將確定下一級別的遞歸調用需要在執行該操作時,它將在該時間點調用該lambda, 以在該時間 點即在調用它之前構造下一個遞歸函數。
不是這樣的方式提前為Y1
正在試圖做的事。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.