关于defmulti源的问题

时间:2017-03-03 13:34:14

标签: clojure

  1. 我无法注意到作者更喜欢多次调用(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)
     ...]
    
  2. 我认为这是好的(在性能方面),因为它定义了一个宏,它将在编译期间执行?

    1. 我还不确定我是否理解调用宏的评估过程。以(defmulti ...)为例,如果我错了,请纠正我:在编译期间,宏展开,其结果是调用特殊let形式,然后转换为字节码。那又怎么样?

    2. 假装我们正在定义一个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)
       ...]
      
    3. var hasRoot究竟是什么意思?什么是Unbound

1 个答案:

答案 0 :(得分:1)

  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

  2. 然后将字节码加载到JVM中并执行。

  3. 我怀疑这会有所作为。

  4. var可以有线程区域绑定,这意味着每个线程可以看到不同的值。根绑定是var初始化的值。线程区域绑定不会压缩根绑定,它只是遮住它。 Unbound是对没有根绑定而创建的变量的实现优化。

    查看clojure.core/binding了解如何设置线程区域设置值。

相关问题