Clojure 2024 调查问卷! 中分享您的想法。

欢迎!请查阅关于页面了解有关此功能的一些更多信息。

0
Clojure

函数组合函数 `comp` 在例如 `(apply comp large-seq-of-fns)` 的情况下效率很低,因为它的 `arity-greater-than-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
user> (let [coll (doall (take 1000000 (repeat inc)))
       f1 (apply comp* coll)
       f2 (apply comp coll)]
       执行基准测试 (f1 0) :verbose)
       打印 "---------------------------------------")
       执行基准测试 (f2 0) :verbose)
amd64 Linux 3.4.2-gentoo 2 核心进程
OpenJDK 64位服务器虚拟机 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 毫秒)
         执行时间置信水平下限:105.609401 毫秒,95.0% CI: (105.609401 毫秒, 105.622918 毫秒)
         执行时间置信水平上限:122.353763 毫秒,95.0% CI: (122.353763 毫秒, 122.405315 毫秒)
---------------------------------------
amd64 Linux 3.4.2-gentoo 2 核心进程
OpenJDK 64位服务器虚拟机 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 微秒)
         执行时间置信水平下限:42.781398 毫秒,95.0% CI: (42.781398 毫秒, 42.781398 毫秒)
         执行时间置信水平上限:44.157311 毫秒,95.0% CI: (44.157311 毫秒, 44.158513 毫秒)
nil

0
by

评论由:tsdh发布

好的,我已经追踪到性能差异。这是由于 reverse 创建了一个可以被迭代得比 (完全实现的) LazySeq 快得多的 clojure.lang.PersistentList。如果您以向量或列表的形式在 (apply comp* fncoll) 中提供您的函数集合,那么创建的组合的应用速度与 comp 相当。

因此,对我来说,补丁很棒,也很合理。

0
by

评论者:jafingerhut

补丁 0001-CLJ-1010-Add-a-left-to-right-version-of-comp-comp.patch(日期为 2012-06-11)在 2014-09-05 或附近提交修改 Clojure 之后不再干净地适用于最新的 master。

我没有检查这个补丁是否容易更新。有关更新旧补丁的建议,请参见 http://dev.clojure.org/display/community/Developing Patches 中的“更新旧补丁”部分。

0
by

评论由:tsdh发布

这是适用于 2014-09-08 的 git master 的新补丁。

0
by
参考:[https://clojure.atlassian.net/browse/CLJ-1010](https://clojure.atlassian.net/browse/CLJ-1010)(由tsdh报告)
...