2024 Clojure状态调查! 分享你的想法。

欢迎!请见 关于 页面以了解这个工作方式的相关信息。

0
Clojure

取第一个n个元素的可变函数在每个索引上调用rem,与比较操作相对昂贵。它可以直接从N开始计数,因为步长是固定的。

5 答案

0

评论来自:[email protected]

附上补丁。在如(time (transduce (take-nth 13) + (range 1e7)))这样的简单测试中大约快25%。

(time (transduce (take-nth 13) + (range 1e7)))

0

评论来自:[email protected]

我没有担心(take-nth 0)的情况,但我的补丁确实给出了不同的结果。当前实现在rem时会产生除零错误。我的补丁则只会返回第一个元素一次。常规集合版本则返回第一个元素无限序列。我不认为有人期望从0的情况得到合理的答案,所以我没有尝试做任何特殊处理。

0

评论来自:michaelblume

很好=)

我认为可变版本的版本应该尽可能地与集合版本匹配,但我不认为有办法编写一个将有限序列转换为无限序列的可变函数,所以很遗憾。

也许我们可以同时更改可变函数和集合的arity,以便在zero时抛出异常?

0
by
_评论由:reborg_发表

GIGO案例,但是rem也有责任


user=> (take-nth 2.5 (range 10))
(0 3 6 9)
user=> (sequence (take-nth 2.5) (range 10))
(0 5)


Steve(CLJ-1665-faster-take-nth-transducer-without-rem.patch)的补丁仅缺少一个转换为int的类型转换来解决上述问题


(defn take-nth [n]
  (fn [rf]
    (let [n (int n)
          iv (volatile! 1)]
      (fn
        ([] (rf))
        ([result] (rf result))
        ([result input]
         (let [i (vswap! iv dec)]
           (if (zero? i)
             (do (vreset! iv n)
                 (rf result input))
             result)))))))


0
by
欢迎使用Clojure问答社区,在这里您可以提出问题,并从Clojure社区成员那里获取答案。
...