2011-04-13 76 views

回答

4

从源代码:

clojure.lang.Cons(严格列表元素,clojure.lang.PersistentList很相似),https://github.com/clojure/clojure/blob/1.2.0/src/jvm/clojure/lang/Cons.java#L34

public Object first(){ 
    return _first; 
} 

clojure.lang.LazySeq(懒惰序列元素),https://github.com/clojure/clojure/blob/1.2.0/src/jvm/clojure/lang/LazySeq.java#L77

public Object first(){ 
    seq(); 
    if(s == null) 
     return null; 
    return s.first(); 
} 

其中

final synchronized Object sval(){ 
    if(fn != null) 
     { 
     try 
      { 
      sv = fn.invoke(); 
      fn = null; 
      } 
     catch(Exception e) 
      { 
      throw new RuntimeException(e); 
      } 
     } 
    if(sv != null) 
     return sv; 
    return s; 
} 

final synchronized public ISeq seq(){ 
    sval(); 
    if(sv != null) 
     { 
     Object ls = sv; 
     sv = null; 
     while(ls instanceof LazySeq) 
      { 
      ls = ((LazySeq)ls).sval(); 
      } 
     s = RT.seq(ls); 
     } 
    return s; 
} 

所以你是绝对是付出代价。它很大程度上取决于每个特定用例的价格对您的影响程度,以及它是否被内存节省和缺乏懒惰评估为您购买的浪费计算所抵消。

3

有一个懒惰结构的开销(pmjordan的答案是伟大的给你血淋淋的细节.....)。我非常粗略的估计是你支付2-5倍的罚款。

然而,也有一些上升空间:

  • 懒惰计算意味着数据的工作集可能更小,因为需要的时候,才会创建。这可能提高您的缓存利用率,并因此在某些情况下提高性能
  • 延迟评估可帮助您编写更简单,更干净的代码。所以你可以专注于编写更好的算法。拥有更好算法(例如O(n log n)vs O(n^2))的好处可能比懒惰评估的开销多得多

我的建议是使用懒惰评估除非你确定你处于一种真正需要高性能并且无法负担开销的情况下(例如图像处理或类似的东西....)