2024年Clojure现状调查!中分享您的想法。

欢迎!请参阅关于页面以了解有关其工作方式的更多信息。

0投票
Clojure

函数组合功能《comp》在《(apply comp large-seq-of-fns)》等情况下效率非常低,因为其具有三个以上参数的版本会反转序列。

如果有一个替代的《comp**》(或任何其他)函数,它就像《comp》一样,但以左到右的方式组合,那就太好了。

7个答案

0投票

评论由:tsdh

这是一个实现示例。

0投票

评论由:tsdh

我的补丁有一些奇怪之处。使用comp**创建的大型函数序列的组合与使用comp相比要快得多,这是预期的,因为不需要反转序列。

然而,奇怪的是,使用《comp》创建的复合函数(虽然《comp》的任意参数版本是用《comp**》定义的:`(apply comp* (reverse (list* f1 f2 f3 fs)))`)比使用comp**创建的快10-20%左右。

有关一些基准测试细节,请参阅:https://groups.google.com/d/msg/clojure/MizwTxHwLE4/hGLrMfetlP8J

0投票
_评论由:tsdh_

这里有一些基准测试。


user> (use 'criterium.core)
nil
user> (let [coll (doall (take 1000000 (repeat inc)))
       f1 (apply comp* coll)
       f2 (apply comp coll)]
       (bench (f1 0) :verbose)
       (println "---------------------------------------")
       (bench (f2 0) :verbose))
amd64 Linux 3.4.2-gentoo 2 cpu(s)
OpenJDK 64-Bit Server VM 22.0-b10
运行时参数:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n -XX:+TieredCompilation -Xmx1G -Dclojure.compile.path=/home/horn/Repos/clj/testi/target/classes -Dtesti.version=0.1.0-SNAPSHOT -Dclojure.debug=false
评估次数: 600
            平均值执行时间: 112.324465 毫秒  95.0% CI: (112.247218 毫秒, 112.380682 毫秒)
    标准差执行时间: 6.513809 毫秒  95.0% CI: (6.477450 毫秒, 6.553029 毫秒)
         执行时间下限 CI: 105.609401 毫秒  95.0% CI: (105.609401 毫秒, 105.622918 毫秒)
         执行时间上限 CI: 122.353763 毫秒  95.0% CI: (122.353763 毫秒, 122.405315 毫秒)
---------------------------------------
amd64 Linux 3.4.2-gentoo 2 cpu(s)
OpenJDK 64-Bit Server VM 22.0-b10
运行时参数:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n -XX:+TieredCompilation -Xmx1G -Dclojure.compile.path=/home/horn/Repos/clj/testi/target/classes -Dtesti.version=0.1.0-SNAPSHOT -Dclojure.debug=false
评估次数: 1440
             平均值执行时间: 43.519663 毫秒  95.0% CI: (43.516732 毫秒, 43.524062 毫秒)
    标准差执行时间: 492.299089 微秒  95.0% CI: (490.829889 微秒, 494.198137 微秒)
         执行时间下限 CI: 42.781398 毫秒  95.0% CI: (42.781398 毫秒, 42.781398 毫秒)
         执行时间上限 CI: 44.157311 毫秒  95.0% CI: (44.157311 毫秒, 44.158513 毫秒)
nil

0投票

评论由:tsdh

好的,我已经追踪到性能差异。这来自于reverse创建了一个可以被快速迭代的clojure.lang.PersistentList,而一个(完全实现的)LazySeq则不能。如果你将fncoll作为向量或列表提供给(apply comp* fncoll),所创建的复合应用的性能与comp相同。

因此,我认为这个补丁很好,并且是合理的。

0投票

评论者:jafingerhut

2012年6月11日创建的补丁0001-CLJ-1010-Add-a-left-to-right-version-of-comp-comp.patch在Clojure于2014年9月5日或之前做出的某些提交后不再适用于最新主分支。

我没有检查此补丁是否容易更新。请参阅http://dev.clojure.org/display/community/Developing Patches部分,以获取有关如何更新补丁的建议。

0投票

评论由:tsdh

这是一个更新后的补丁,它适用于2014年9月8日的git master。

0投票
...