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%,尽管 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
用户> (doall (取 1000000 (重复 (递增))))
       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 ms  95.0% CI: (112.247218 ms, 112.380682 ms)
    执行时间标准偏差:6.513809 ms  95.0% CI: (6.477450 ms, 6.553029 ms)
         执行时间下限置信区间:105.609401 ms  95.0% CI: (105.609401 ms, 105.622918 ms)
         执行时间上限置信区间:122.353763 ms  95.0% CI: (122.353763 ms, 122.405315 ms)
---------------------------------------
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 ms  95.0% CI: (43.516732 ms, 43.524062 ms)
    执行时间标准偏差:492.299089 us  95.0% CI: (490.829889 us, 494.198137 us)
         执行时间下限置信区间:42.781398 ms  95.0% CI: (42.781398 ms, 42.781398 ms)
         执行时间上限置信区间:44.157311 ms  95.0% CI: (44.157311 ms, 44.158513 ms)
nil

0

评论者:tsdh

好的,我已经追踪到性能差异的原因。这是因为 reverse 创建了一个 clojure.lang.PersistentList,它的迭代速度比(完全实现的)LazySeq 快得多。如果您将 fncoll 作为向量或列表提供到 (apply comp* fncoll) 中,创建的复合应用速度与 comp 的速度相同。

所以对我来说,这个补丁是好的并且有意义。

0

评论者:jafingerhut

补丁 0001-CLJ-1010-Add-a-left-to-right-version-of-comp-comp.patch 日期为 2012 年 6 月 11 日,由于在某些对 Clojure 的提交后,它不再干净地应用于 2014 年 9 月 5 日附近的最新的主分支。

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

0

评论者:tsdh

这是一个更新的补丁,适用于 2014 年 9 月 8 日的 git 主分支。

0
参考: https://clojure.atlassian.net/browse/CLJ-1010 (由tsdh提出)
...