2013-02-21 84 views
23

之間的區別困惑誰能解釋一下這個區別嗎?我不認爲我理解我諮詢過的教科書/網站的概念。讓與讓*在計劃

+2

[Let and Let \ *]計劃混淆(http:// stackoverflow。com/questions/8036840 /方案混亂的讓和讓) – 2013-02-21 13:34:32

+4

@DavidPfeffer - 似乎不是一個愚蠢的。那個人問的是嵌套'let's和'let *'的一個非常具體的相互作用,而這是一個總體概述。 – Inaimathi 2013-02-21 15:05:29

+0

簡單地把人機解釋爲機器執行:o – Nishant 2014-01-11 10:23:18

回答

23

如果使用let,則不能引用先前在同一個let表達式中定義的綁定。例如,這是不行的:

(let ((x 10) 
     (y (+ x 6))) ; error! unbound identifier in module in: x 
    y) 

但是如果你使用let*,它可以參考以前的綁定在同一個let*表達:

(let* ((x 10) 
     (y (+ x 6))) ; works fine 
    y) 
=> 16 

這是文件中的所有here

+1

我在文檔中看不清楚(你的鏈接點,當前版本5.3.6),所以我也很困惑。 'let'的文檔中說:「第一種形式從'val-exprs'從左到右評估......」,所以並不清楚它們是否被並行評估。 – Alexey 2014-01-03 10:03:48

+0

@Alexey它不會並行評估它們。正如文檔所說,*「第一種形式從左到右評估'val-exprs',爲每個'id'創建一個新位置,並將這些值放到位置」* - 意思是,首先評估它們並且收集結果值,並且只爲每個*'id' *創建***然後***新位置,並且將這些值分別放置在其位置中。如果*'val-exprs' *中的一個突變存儲器(即數據,如列表或結構體),則仍然可以看到序列性。 – 2017-01-07 14:07:11

26

Let平行,(種;見下文)let*是連續的。 Let翻譯爲

((lambda(a b c) ... body ...) 
    a-value 
    b-value 
    c-value) 

let*作爲

((lambda(a) 
    ((lambda(b) 
     ((lambda(c) ... body ...) 
     c-value)) 
    b-value)) 
    a-value) 

,並因此創建嵌套範圍塊,其中b-value表達可以指a,並c-value表達可以指兩個baa-value屬於外部範圍。這也相當於

(let ((a a-value)) 
    (let ((b b-value)) 
    (let ((c c-value)) 
     ... body ...))) 

還有letrec,允許遞歸綁定,其中所有變量和表達式屬於一個共享範圍,並且可以相互引用(與關於初始化一些注意事項)。它相當於要麼

(let ((a *undefined*) (b *undefined*) (c *undefined*)) 
    (set! a a-value) 
    (set! b b-value) 
    (set! c c-value) 
    ... body ...) 

in Racket,也可如方案letrec*,由於R6RS),或

(let ((a *undefined*) (b *undefined*) (c *undefined*)) 
    (let ((_x_ a-value) (_y_ b-value) (_z_ c-value)) ; unique identifiers 
    (set! a _x_) 
    (set! b _y_) 
    (set! c _z_) 
    ... body ...)) 

in Scheme)。

更新:let實際上並沒有實際評估它的值表達式,而只是它們都在let窗體出現的相同初始環境中進行評估。這也是從lambda基翻譯明確:第一值表達式進行求值的每個在相同的,外部環境,並收集所得的值,並且僅然後新的位置爲每個ID創建並將這些值放在每個位置。如果其中一個值表達式對一個存儲器(即數據,如列表或結構體)進行變異,我們仍然可以看到序列性。