首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Clojure中let和let*的区别

Clojure中let和let*的区别
EN

Stack Overflow用户
提问于 2015-07-27 19:01:09
回答 2查看 2.6K关注 0票数 16

请考虑以下宏:

代码语言:javascript
复制
(defmacro somemacro []
    (list 'let ['somevar "Value"] 'somevar))

扩展它会产生以下结果:

代码语言:javascript
复制
(macroexpand '(somemacro))

结果:

代码语言:javascript
复制
(let* [somevar "Value"] somevar)

我有两个关于let* (星号)的问题:

  • 什么意思?(特别是:是否在某个地方记录在案?)
  • 为什么宏没有用“正常”let展开?(也就是说,不用星号就可以了)两者的结果(在我的实验中)是一样的。有反例吗?

不幸的是,我找不到任何关于let*的“正式”文档,这就是我在这里问的原因。

我已经考虑过的消息来源:

代码语言:javascript
复制
(doc let*)  ; --> nil
(source let*)  ; --> source not found
  1. https://clojuredocs.org/clojure.core ->我看到这里不让*(虽然有列表*)
  2. https://clojuredocs.org/clojure.core/let -->只在评论中提到过一次,对我来说还不完全清楚: Nota : let in Clojure就像Scheme中的let* -每个init-expr都可以访问前面的绑定表单。(也有let*,但它或多或少没有破坏,实际上是底层实现。)
  3. 共通Lisp ->这个问题是关于普通的lisp的,但是在Clojure中可能是一样的?
  4. 这个答案:https://stackoverflow.com/a/5084339/3398271在Clojure中的基本意思是"foo*类似foo,但在某种程度上不同,您可能想要foo“。换句话说,这意味着该代码的作者无法为第二个函数找到一个更好的名称,所以他们只是给了它一颗星。

但如果是这样的话,问题仍然存在,究竟有什么不同?

  1. 在计划里?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-07-27 19:42:26

let*是一个内部实现细节。let是一个用let*实现的宏。https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L4301

let将参数毁伤添加到let*。这是Clojure中xyzxyz*的标准模式,*版本没有文档化。listlist*是一个例外。

票数 20
EN

Stack Overflow用户

发布于 2016-03-14 21:54:19

我想补充一点,macroexpand返回let*而不是let的原因可以在macroexpand中找到。

在窗体上反复调用宏展开-1,直到它不再表示宏窗体,然后返回它。

因此,macroexpand-1的第一个调用返回(let [somevar "Value"] somevar),第二个调用将let扩展为let*

的确,

代码语言:javascript
复制
user=> (println (clojure.string/join "\n" (take 3 (iterate macroexpand-1 '(somemacro)))))
(somemacro)
(let [somevar "Value"] somevar)
(let* [somevar "Value"] somevar)
nil

如果要在宏中使用析构,则输出将更有趣:

代码语言:javascript
复制
user=> (defmacro destructuring-macro [] `(let [[x y z] [:x :y :z]] y))
#'user/destructuring-macro

user=> (println (clojure.string/join "\n" (take 3 (iterate macroexpand-1 '(destructuring-macro)))))
(destructuring-macro)
(clojure.core/let [[testing.core/x testing.core/y testing.core/z] [:x :y :z]] testing.core/y)
(let* [vec__8356 [:x :y :z] x (clojure.core/nth vec__8356 0 nil) y (clojure.core/nth vec__8356 1 nil) z (clojure.core/nth vec__8356 2 nil)] testing.core/y)
nil

注意,let被语法引号完全限定,因为它不是一个特殊的形式(尽管它的文档说明它是)。底层的特殊形式是let*,它不是由语法引号完全限定的。

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

https://stackoverflow.com/questions/31661187

复制
相关文章

相似问题

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