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开发者指向这个问题,看看他们是否已经意识到了这一点。

by
我实现了最初的 :extend-via-metadata 支持,并证实我是基于错误的假设(即实际实现是先选择的,然后才是元数据)来实现的。

测试甚至反映了这个假设。
https://github.com/clojure/clojurescript/blob/d64b2333f3127b51dbe410874a7cdff4bac1edf8/src/test/cljs/cljs/core_test.cljs#L1756-L1777
by
你知道这在 JavaScript 实现中是否被认为是一个错误,值得修改吗?
by
是的,这可能意味着它应该与 Clojure 的行为相符。

但是,这意味着使用 :extend-via-metadata 的协议将整体变“慢”,因为它无法采取目前所采取的“捷径”。
by
我刚刚遇到了这个问题。这是又一个使编写可移植代码成为问题的细微差异。
...