簡體   English   中英

為什么用lambda修復堆棧包裝函數會溢出?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM