我无法注意到作者更喜欢多次调用(first options)
而不是缓存结果:
[docstring (if (string? (first options))
(first options)
nil)
options (if (string? (first options))
(next options)
options)
m (if (map? (first options))
(first options)
{})
options (if (map? (first options))
(next options)
options)
...]
我认为这是好的(在性能方面),因为它定义了一个宏,它将在编译期间执行?
我还不确定我是否理解调用宏的评估过程。以(defmulti ...)
为例,如果我错了,请纠正我:在编译期间,宏展开,其结果是调用特殊let
形式,然后转换为字节码。那又怎么样?
假装我们正在定义一个fn而不是一个宏,是否值得为{em>缓存引入一个额外的符号(first options)
的结果:
[f (first options)
docstring (if (string? f)
f
nil)
options (if (string? f)
(next options)
options)
f (first options)
m (if (map? f)
f
{})
options (if (map? f)
(next options)
options)
...]
var hasRoot
究竟是什么意思?什么是Unbound
?
答案 0 :(得分:1)
是的,调用first
的速度很快。 varargs表示为序列,特别是clojure.lang.ArraySeq
(至少直到一定数量的参数)。
user=> ((fn [& args] (type args)) 1 2 3)
clojure.lang.ArraySeq
first()
上ArraySeq
的实现是一个数组查找
public Object first(){
if(array != null)
return array[i];
return null;
}
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ArraySeq.java#L69
然后将字节码加载到JVM中并执行。
我怀疑这会有所作为。
var可以有线程区域绑定,这意味着每个线程可以看到不同的值。根绑定是var初始化的值。线程区域绑定不会压缩根绑定,它只是遮住它。 Unbound
是对没有根绑定而创建的变量的实现优化。
查看clojure.core/binding
了解如何设置线程区域设置值。