如何使用lambda实现let*

use*_*209 2 lambda scheme lambda-calculus let

我正在做lambda演算,在我的教科书中,它说你将如何let*使用lambda演算.

我的答案:x,y和z是参数; v1,v2和v3参数; e是身体:

((lambda (x y z) (e)) v1 v2 v3)
Run Code Online (Sandbox Code Playgroud)

书中的答案:

  ((lambda(x)
    ((lambda(y)
      ((lambda(z) e) v3))
      v2))
    v1)
Run Code Online (Sandbox Code Playgroud)

我不确定我的回答是否相同.如果没有,为什么我的回答是错误的,如何得出原始答案?

Lil*_*ung 10

更新2:我已经意识到我的原始答案是正确的并且回滚到原始答案,但会添加一些澄清的说明.

在Scheme中,let*允许以后的值依赖于之前的值.因此,例如,您可以编写(使用通常的语法):

(let* ((foo 3)
       (bar (+ foo 1))
       (baz (* bar 2)))
  (* foo bar baz))
Run Code Online (Sandbox Code Playgroud)

它绑定foo到3,bar到4,baz到8,并返回72.您的教科书的实现允许这样做.

但是,您的实现不允许这样做 - 它需要独立评估所有值.然而,它是正确的实现let,而不是let*.

教科书答案的工作方式是先前的值在之后的值之前被绑定.例如,教科书实现中的上述代码如下:

((lambda (foo)
  ((lambda (bar)
    ((lambda (baz) (* foo bar baz)) (* bar 2)))
    (+ foo 1)))
  3)
Run Code Online (Sandbox Code Playgroud)

但是,如果您尝试以相同的方式使用您的实现:

((lambda (foo bar baz) (* foo bar baz)) 8 (+ foo 1) (* bar 2))
; Error - foo and bar aren't bound
Run Code Online (Sandbox Code Playgroud)

然后fooin (+ foo 1)将是未绑定的,因为foo不在范围内(对于barin (* bar 2).


作为旁注,(e)你的实现应该e就像在教科书的实现中一样; 前者是一个thunk,而后者只是一个表达.