(let ((+ *)
(* +))
(+ 3 (* 4 5)))
输出:27
(let ((+ *))
(+ 3 (* 4 5)))
输出:60
我不明白let
是如何运作的。任何人都可以帮助我吗?
答案 0 :(得分:2)
可让强>
let
绑定在 parallel 中,因为
(let ((+ *) (* +))
(+ 3 (* 4 5)))
实际上扩展为
((lambda (+ *)
(+ 3 (* 4 5)))
* +)
所以Scheme通常会这样做:
*
和+
会根据某些序列*
和+
)进行评估>
+
和*
(这也发生在一些序列中,但在两种情况下都无关紧要)(* 3 (+ 4 5))
。只需添加printf
即可确认:
(let ((+ *) (* +))
(printf "+ is ~a and * is ~a \n" + *)
(+ 3 (* 4 5)))
=>
+ is #<procedure:*> and * is #<procedure:+>
27
可让* 强>
如果您希望绑定发生在序列中,那么您必须使用 let *,因为
(let* ((+ *) (* +))
(+ 3 (* 4 5)))
扩展为
((lambda (+)
((lambda (*)
(+ 3 (* 4 5)))
+))
*)
所以
*
绑定到+
+
已绑定到*
,再次绑定到*
,这实际上没有效果(* 3 (* 4 5))
并且因为第二个绑定没有效果,所以这相当于简单地
(let ((+ *))
(+ 3 (* 4 5)))
答案 1 :(得分:1)
在第一个表达式中,*
绑定到+
的原始值,+
绑定到*
的原始值。因此(+ 3 (* 4 5))
与原始绑定相当于(* 3 (+ 4 5))
。这与中缀表达式3 * (4 + 5)
相同,当然是27。
在第二个表达式中,+
绑定到*
的原始值,*
未更改。因此(+ 3 (* 4 5))
与原始绑定相当于(* 3 (* 4 5))
,与中缀表达式3 * (4 * 5)
相同,即60。
这里最重要的注意事项是let
执行并行绑定。这意味着在(let ((+ *) (* +)) ...)
之类的表达式中,首先获取*
和+
的原始值,然后+
和*
同时绑定 。这就是为什么新*
的旧值为+
,而不是其新值。
我最近写了a post about the differences between the various let
forms。请注意let
和let*
之间的差异。
答案 2 :(得分:1)
使用Stepper!
Racket有一个很好的步进器,可以帮助你回答这个问题。将您的代码粘贴到缓冲区中,切换到&#34;中级学生&#34;语言,然后单击&#34;步骤&#34;按钮。您将看到突出显示的步骤序列。
答案 3 :(得分:-1)
因为:
(let ((+ *)
(* +))
(+ 3 (* 4 5)))
严格等同于(这称为标识符重命名):
(let ((PLUS *)
(TIMES +))
(PLUS 3 (TIMES 4 5)))
因为,正如其他答案所指出的那样,绑定是并行完成的。 这意味着此处实际评估的表达式为:
(* 3 (+ 4 5))
确实是27。