【问题标题】:Reduce a lazy sequence like a loop with a condition in Clojure在 Clojure 中减少一个惰性序列,例如带有条件的循环
【发布时间】:2013-03-26 07:02:46
【问题描述】:

我有一个无限的惰性序列,它产生一个“前导”和一个“模式重复”,这种序列的一个简单示例可以在 Clojure 中实现:

(def infinite-lazy-sequence
  (lazy-cat [4] (cycle [1 2 3])))

=> (take 20 infinite-lazy-sequence)
(4 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1)

我想获得构成这个infinite-lazy-sequence 的元素的set,这是使用loop 实现它的一种方法:

(loop
  [[head & tail] infinite-lazy-sequence
   result #{}]
  (if (contains? result head)
    result
    (recur tail (conj result head))))

=> #{1 2 3 4}

这里的问题是:使用reduce 是否可以达到相同的结果?并使用take-while?

编辑:

使用 clojure-1.5.1 和 perforate-0.2.4 进行基准测试

建议loop-recur 实施:

Case:  :loop-recur
Evaluation count : 60 in 60 samples of 1 calls.
             Execution time mean : 1.054975 sec
    Execution time std-deviation : 26.316442 ms
   Execution time lower quantile : 1.026187 sec ( 2.5%)
   Execution time upper quantile : 1.125854 sec (97.5%)

@sw1nn reduce-reduced 实现:

Case:  :reduce-reduced
Evaluation count : 120 in 60 samples of 2 calls.
             Execution time mean : 875.091831 ms
    Execution time std-deviation : 19.745142 ms
   Execution time lower quantile : 850.871606 ms ( 2.5%)
   Execution time upper quantile : 921.947759 ms (97.5%)

【问题讨论】:

  • 所以在重复模式开始重复之前,无限序列中的任何元素都不会出现两次,对吗?
  • 是的,没错。不幸的是,我不知道序言可能有多长......好点。

标签: clojure


【解决方案1】:

Clojure 1.5 添加了reduced 以允许减少短路...

 (reduce (fn [a v] (if-not (a v) (conj a v) (reduced a))) 
         #{} 
         infinite-lazy-sequence)
 => #{1 2 3 4}

【讨论】:

  • 谢谢@sw1nn,我刚刚用我的目标infinite-lazy-sequence 对它进行了基准测试,而且你的减少减少的版本似乎也更快与Clojure 1.5.1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 2012-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多