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.coreisinntess

我建议您进入 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 的协议整体会变慢,因为它无法采取当前所采取的“捷径”。
我刚刚遇到了这个问题。又一个使编写便携代码成为问题的细微差异。
...