可能所有有经验的elisper都会在某些时候发现,像这样的代码被破坏了:
(let ((a 3)
(b 4)
(c (+ a b)))
c)当在绑定子句中引用刚绑定的变量时,应该改用let*形式。
我只是想知道--为什么一个看似错误的行为是默认的?不管用户如何使用,总是选择let*是否有任何风险?
发布于 2012-08-07 16:57:55
我学到的主要是历史原因,但它可能仍然有效:因为let做并行赋值,变量之间没有数据依赖可能会给编译器带来灵活性,编译速度或空间,并编译成比let*快得多的东西。我不知道elisp编译器使用了多少。
稍微搜索一下,就会发现Common Lisp也有类似的问题:LET versus LET* in Common Lisp
发布于 2012-08-06 09:28:51
任何let*表单都可以使用轻松地(和机械地)使用let表示。例如,如果我们没有let*特殊形式,我们可以表示
(let* ((a 3)
(b 4)
(c (+ a b)))
c)作为:
(let ((a 3))
(let ((b 4))
(let ((c (+ a b)))
c)))另一方面,如果可能的话,使用let*表示某些let表单是相当困难的。如果不引入额外的临时变量或深奥的按位操作,则无法使用let*表示以下let形式。
(let ((x y) (y x)) ; swap x and y
...)所以,从这个意义上说,我认为let比let*更基础。
发布于 2012-08-06 09:14:08
这样做是不正确的。
(let ((a 10)
(b a)) <- error
b)这样做是正确的:
(let* ((a 10)
(b a))
b) <- will evaluate to 10.第一种情况下的错误是由于let的语义造成的。
let*将新符号添加到现有环境中,并在其中对其进行计算。
let创建一个新的环境,评估当前环境中的新符号,并且在所有新符号的评估结束时,新环境将被丢弃,以评估(let ()代码)的代码。
let*是语法糖,用于
(let ((a xxx))
(let ((b a)) ...)而let是syntactic sugar for
((lambda (a)
...)
val_a)第二种形式是更常见的,所以也许他们想给它起一个更短的名字……
https://stackoverflow.com/questions/11821423
复制相似问题