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

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

0投票
Clojure

函数组合函数comp在使用如(apply comp large-seq-of-fns)等场景中效率相当低,因为其超过3个参数版本的序列是反向的。

如果有一个函数像comp**(或任何其他什么)可以作为替代,那么它将和comp类似,但以从左到右的方式组合。

7 个回答

0投票

评论者:tsdh

这里有一个实现。

0投票

评论者:tsdh

我的补丁有点奇怪。与使用comp相比,使用comp**创建函数组合的效率要高得多,这是预期的,因为不需要反转序列。

然而,奇怪的是,用comp创建的组合评估速度比用comp**创建的组合快约10-20%,尽管读者-arity版本的comp是用comp**定义的:`(apply comp* (reverse (list* f1 f2 f3 fs)))`。

有关基准测试的详细信息,请参阅: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 (应用复合比较)
       (bench (f1 0) :verbose)
       (println "---------------------------------------")
       (bench (f2 0) :verbose))
amd64 Linux 3.4.2-gentoo 2 个 cpu
OpenJDK 64 位服务器 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
OpenJDK 64 位服务器 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投票
by

评论者:tsdh

好的,我追踪到了性能差异的原因。这是由于reverse创建了一个clojure.lang.PersistentList,它的迭代速度比(full realized) LazySeq快得多。如果你将fncoll提供为向量或列表到(apply comp* fncoll)中,则创建的复合函数应用与comp一样快。

因此,对我来说,该补丁很好且有意义。

0投票
by

评论人:jafingerhut

补丁 0001-CLJ-1010-Add-a-left-to-right-version-of-comp-comp.patch,日期为 2012 年 6 月 11 日,在 Clojure 于 2014 年 9 月 5 日前后进行了一些提交后,不再干净地应用于最新的 master。

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

0投票
by

评论者:tsdh

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

0投票
...