我正在做lambda演算,在我的教科书中,它说你如何使用lambda演算写let*
。
我的回答:x,y和z是参数; v1,v2和v3参数; e是身体:
((lambda (x y z) (e)) v1 v2 v3)
书中的答案:
((lambda(x)
((lambda(y)
((lambda(z) e) v3))
v2))
v1)
我不确定我的答案是否相同。如果没有,为什么我的回答是错误的,如何得出原始答案?
答案 0 :(得分:10)
更新2:我意识到我的原始答案是正确的并且回滚到原始答案,但会添加一些澄清的说明。
在Scheme中,let*
允许以后的值依赖于之前的值。因此,例如,您可以编写(使用通常的语法):
(let* ((foo 3)
(bar (+ foo 1))
(baz (* bar 2)))
(* foo bar baz))
将foo
绑定到3,将bar
绑定到4,将baz
绑定到8,然后返回72.您的教科书的实现允许这样做。
但是,您的实现不允许这样做 - 它需要独立评估所有值。但是,它是let
的正确实现,而不是let*
。
教科书答案的工作方式是先前的值在之后的值之前被绑定。 例如,教科书实现中的上述代码如下:
((lambda (foo)
((lambda (bar)
((lambda (baz) (* foo bar baz)) (* bar 2)))
(+ foo 1)))
3)
但是,如果您尝试以相同的方式使用您的实现:
((lambda (foo bar baz) (* foo bar baz)) 8 (+ foo 1) (* bar 2))
; Error - foo and bar aren't bound
然后foo
中的(+ foo 1)
将不受约束,因为foo
不在范围内(bar
中的(* bar 2)
也是如此。
作为旁注,实施中的(e)
应该只是e
,就像教科书的实施一样;前者是一个thunk,而后者只是一个表达。
答案 1 :(得分:0)
Istvan的回答是正确的,但基本上,您的代码和教科书之间的差异是let
和let*
之间的差异。基本上,let*
是let
的嵌套系列,事实上,let*
的典型定义如下:
(define-syntax let*
(syntax-rules ()
;; if no bindings, same as let
((let* () body ...)
(let () body ...))
;; otherwise, take one binding, then nest the rest
((let* (binding next ...) body ...)
(let (binding)
(let* (next ...)
body ...)))))