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

欢迎!请参阅 关于页面 了解更多关于这是如何工作的信息。

+6
Clojure

clojure.walk 中的条件分派速度慢且不易扩展。在 CLJ-1105 之前,它不支持记录。

方法: 使用协议重新实现 clojure.walk。公共 API 保持不变。如果需要,用户可以扩展 {{walk}} 协议到其他类型(例如,Java 集合)。与 CLJ-1105 一样,这个版本的 clojure.walk 支持记录。

补丁: 0002-CLJ-1239-protocol-dispatch-for-clojure.walk.patch

性能: 我的测试表明,这比原始 clojure.walk 快 1.5-2 倍。基准测试请参阅 https://github.com/stuartsierra/clojure.walk2

风险: 这种方法可能会破坏依赖于旧 clojure.walk 的类型特定行为的使用者代码。在运行完整的 Clojure 测试套件时,我发现了(并修复了)在 clojure.walk 的单元测试中没有出现的断点。例如,请参阅(链接:https://github.com/stuartsierra/clojure.walk2/commit/730eb756dcc424aa535d0872bd626079955c3892 文本:clojure.walk2 中的 730eb75 提交)。

10 个答案

0

评论由:vmarcinko

看起来,如目前所示,遍历树结构并替换形式不会保留数据结构中所含的元数据。

0

评论由:jafingerhut

自 2013 年 11 月 22 日提交 CLJ-1105 补丁以来,补丁 0001-CLJ-1239-protocol-dispatch-for-clojure.walk.patch 已不再干净地适用于最新的 Clojure master。根据描述,似乎是为了该补丁或此补丁,而不是两者,因此我不确定这个补丁,甚至这个问题应该怎么办。

0
作者:

评论者:alexmiller

此补丁和工单仍有资格在未来版本中发布。

0
作者:

评论者:stuart.sierra

添加了新的补丁,该补丁应用于CLJ-1105之后最新的master代码。

0
作者:
评论者:[email protected]

与常规map相比,该补丁的行为可能会令人惊讶


(clojure.walk/prewalk-replace {[:a 1] nil} {:a 1, :b 2})
;=> {:b 2}

(defrecord Foo [a b])
(clojure.walk/prewalk-replace {[:a 1] nil} (map->Foo {:a 1, :b 2}))
;=> #user.Foo{:a 1, :b 2}


注意:从map中删除了{{[:a 1]}}条目,但没有从record中删除。

以下是一种不受此问题困扰的实现方式,但它会进行令人担心的类名称杂糅:https://github.com/LonoCloud/synthread/blob/a315f861e04fd33ba5398adf6b5e75579d18ce4c/src/lonocloud/synthread/impl.clj#L66

也许我们可以扩展defrecord抽象,以更好地支持synthread代码正在笨拙地执行的事情,然后{{walk}}可以利用这一点。
0
作者:

评论者:alexmiller

@Chouser,你能为此创建一个新的工单吗?从已关闭的工单上的评论管理某项工作是很困难的。

0
作者:

评论者:alexmiller

@Chouser - 无需理会!我在想这是否是进入1.6的更改,继续吧:)

0
作者:

评论者:bronsa

亚历克斯,重要的是,clojure-1.6.0在CLJ-1105之后表现出与Chouser描述此补丁相同的特性。

0

评论者:glts

当前clojure.walk的实现并没有保存元数据。

如果将来再次审查这个新实现,最好是在可能的地方也保留元素的元数据。

0
参考: https://clojure.atlassian.net/browse/CLJ-1239(由 stuart.sierra 报告)
...