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 的协议将“慢”一点,因为它无法采取当前采取的“快捷方式”。
我刚刚遇到了这个问题。又一个导致编写可移植代码成为问题的微妙差异。
...