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

欢迎!有关如何工作的更多信息,请参阅关于页面。

+3
ClojureScript

如果您扩展一个类型以实现一个协议,然后为该类型创建一个实例,并在其元数据中包含相同的协议的自己的实现,则 ClojureScript 仍将使用从类型中获取的实现,而 Clojure 使用更具体的元数据实现。

以下是一个基于 ClojureScript 协议元数据实现测试的简单示例。

编辑:我在此编辑器中无法使代码示例可展示,请参阅此 Gist:https://gist.github.com/cjohansen/a24257ecb5db15c7e20aaa25ff713b30

(defprotocol ExtMetaProtocol
:extend-via-metadata true
(ext-meta-protocol [x]))

(ext-meta-protocol (with-meta {} {`ext-meta-protocol (fn [_] 1)})) ;;=> 1

(extend-type clojure.lang.PersistentArrayMap
ExtMetaProtocol
(ext-meta-protocol [m]

2))

(ext-meta-protocol {}) ;;=> 2
(ext-meta-protocol (with-meta {} {`ext-meta-protocol (fn [_] 1)})) ;;=> cljs => 2, clj => 1

1 答案

+3

已确认 Clojure 1.10.1 和 ClojureScript 1.10.520 的行为彼此不同,如示例 REPL 会话中所述。对于 cljs,您必须将extend-type clojure.lang.PersistentArrayMap替换为extend-type cljs.core.PersistentArrayMap

我建议进入 Clojurians Slack 的 #cljs-dev 频道,并将 ClojureScript 开发者指向这个问题,看看他们是否已经知道这个。

我实施了初始的 :extend-via-metadata 支持,并确认我是基于错误的假设(即实际实现先于元数据被选择)。

测试甚至反映了那个假设
https://github.com/clojure/clojurescript/blob/d64b2333f3127b51dbe410874a7cdff4bac1edf8/src/test/cljs/cljs/core_test.cljs#L1756-L1777
你知道这是否被视为 JavaScript 实现中的一个错误,值得更改吗?
是的,它应该与 Clojure 的行为相匹配。

然而,这意味着使用 :extend-via-metadata 的协议将变得“整体较慢”,因为它无法采用它目前采用的“捷径”。
我刚刚遇到这个问题。另一个使编写可移植代码成为问题的微妙差异。
...