2024 Clojure 状况调查! 分享您的想法。

欢迎!有关本站如何运作的更多信息,请参阅 关于 页面。

0
Clojure

take-nth 透传器会调用 rem 操作每个索引,这相对于 zero? 测试来说是相对昂贵的。它可以直接从 N 计数到 1 作为步长,因为步长是固定的。

5 个答案

0

评论来自:[email protected]

已附上补丁。在像这样的简单测试中,它的速度提高了约 25%

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

0

评论来自:[email protected]

我没有考虑 (take-nth 0) 的情况,但我的补丁确实给出了不同的结果。当前实现会在 rem 返回除以零错误。我的补丁版本会返回一次第一个元素。常规集合版本会返回第一个元素的无穷序列。我怀疑没有人期望从 0 情况下得到合理的答案,所以我并没有对其做任何特别处理。

0

评论来自:michaelblume

太棒了 =)

我会说透传器版本应该尽可能接近集合版本,但我认为实际上没有方法编写将有限序列转换为无限序列的透传器,所以在这里没有运气。

也许我们可以借此机会同时更改透传器和集合的可变参数数量,使之在零值时抛出异常?

0
评论人: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)的补丁缺少一个cast到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
欢迎来到Clojure问答社区,在这里您可以向Clojure社区成员提问并获得答案。
...