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 支持,并可以确认我是基于错误的假设来实施的(即实际上拾取 impl 在 meta 之前)。

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

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