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

Kev*_*vin 6 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=>
Run Code Online (Sandbox Code Playgroud)

我想知道有多么fn*不同fn,但我似乎无法fn*在文档中找到任何参考.我错过了什么,又有什么fn*不同?

Pau*_*her 12

免责声明:我距离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}用于让编译器知道包含该函数的闭包只会被调用一次,并且它可以执行封闭的本地清除.有关详细信息,请参阅此邮件列表主题.

  • 这是对的.我要补充说`fn*`是一个实现细节,而不是clojure API的一部分; 这就是为什么它不包含在文档中. (2认同)