什么是fn *,它与fn有什么不同?

时间:2014-05-10 21:50:27

标签: clojure

我看了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*有何不同?

1 个答案:

答案 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中由符号FNFNONCE引用。第一个是“裸”fn*,第二个是fn*,其中包含元数据^{:once true},这是lazy-seq使用的版本。

^{:once true}用于让编译器知道包含该函数的闭包只会被调用一次,并且它可以执行封闭的本地清除。有关详细信息,请参阅this mailing list thread