我看了lazy-seq
的来源,我发现了这个:
Clojure 1.4.0
user=> (source lazy-seq)
(defmacro lazy-seq
"Takes a body of expressions that returns an ISeq or nil, and yields
a Seqable object that will invoke the body only the first time seq
is called, and will cache the result and return it on all subsequent
seq calls. See also - realized?"
{:added "1.0"}
[& body]
(list 'new 'clojure.lang.LazySeq (list* '^{:once true} fn* [] body)))
nil
user=>
我想知道fn*
与fn
的区别,但我似乎无法在文档中找到fn*
的任何引用。我错过了什么,以及fn*
有何不同?
答案 0 :(得分:11)
免责声明:我距离Clojure编译专家还有很长的路要走,所以请使用适当数量的盐进行以下操作。
fn*
是fn
的内在版本。很多Clojure都是在Clojure中实现的,但是一些低级函数是用Java实现的; fn*
就是其中之一。
fn
是根据fn*
实施的。来源在这里:
https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L42
fn*
在编译器中实现:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L47
实际上有两个不同版本的fn*
,在Java中由符号FN
和FNONCE
引用。第一个是“裸”fn*
,第二个是fn*
,其中包含元数据^{:once true}
,这是lazy-seq
使用的版本。
^{:once true}
用于让编译器知道包含该函数的闭包只会被调用一次,并且它可以执行封闭的本地清除。有关详细信息,请参阅this mailing list thread。