首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么let*不是默认的let?

为什么let*不是默认的let?
EN

Stack Overflow用户
提问于 2012-08-06 08:50:44
回答 4查看 782关注 0票数 4

可能所有有经验的elisper都会在某些时候发现,像这样的代码被破坏了:

代码语言:javascript
复制
(let ((a 3)
      (b 4)
      (c (+ a b)))
  c)

当在绑定子句中引用刚绑定的变量时,应该改用let*形式。

我只是想知道--为什么一个看似错误的行为是默认的?不管用户如何使用,总是选择let*是否有任何风险?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-08-07 16:57:55

我学到的主要是历史原因,但它可能仍然有效:因为let做并行赋值,变量之间没有数据依赖可能会给编译器带来灵活性,编译速度或空间,并编译成比let*快得多的东西。我不知道elisp编译器使用了多少。

稍微搜索一下,就会发现Common Lisp也有类似的问题:LET versus LET* in Common Lisp

票数 6
EN

Stack Overflow用户

发布于 2012-08-06 09:28:51

任何let*表单都可以使用轻松地(和机械地)使用let表示。例如,如果我们没有let*特殊形式,我们可以表示

代码语言:javascript
复制
(let* ((a 3)
       (b 4)
       (c (+ a b)))
  c)

作为:

代码语言:javascript
复制
(let ((a 3))
  (let ((b 4))
    (let ((c (+ a b)))
      c)))

另一方面,如果可能的话,使用let*表示某些let表单是相当困难的。如果不引入额外的临时变量或深奥的按位操作,则无法使用let*表示以下let形式。

代码语言:javascript
复制
(let ((x y) (y x)) ; swap x and y
  ...)

所以,从这个意义上说,我认为letlet*更基础。

票数 22
EN

Stack Overflow用户

发布于 2012-08-06 09:14:08

这样做是不正确的。

代码语言:javascript
复制
(let ((a 10)
      (b a)) <- error
  b)

这样做是正确的:

代码语言:javascript
复制
(let* ((a 10)
       (b a))
   b) <- will evaluate to 10.

第一种情况下的错误是由于let的语义造成的。

let*将新符号添加到现有环境中,并在其中对其进行计算。

let创建一个新的环境,评估当前环境中的新符号,并且在所有新符号的评估结束时,新环境将被丢弃,以评估(let ()代码)的代码。

let*是语法糖,用于

代码语言:javascript
复制
(let ((a xxx))
  (let ((b a)) ...)

letsyntactic sugar for

代码语言:javascript
复制
((lambda (a)
  ...)
  val_a)

第二种形式是更常见的,所以也许他们想给它起一个更短的名字……

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11821423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档