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

欢迎!有关这个平台如何工作的更多信息,请查看 关于 页面。

0
ClojureScript
{{js->clj}} say


  (cond

    [...]
                
    (coll? x)
    (into (empty x) (map thisfn x))


问题在于 {{(coll? x)}} 检查 ICollection,而 {{(empty x)}} 需要 IEmptyableCollection。当 x 通过第一个测试但未通过第二个测试时,{{js->clj}} 将抛出 "错误:类型 : [object Object] 上未定义 IEmptyableCollection.-empty 协议方法"。

鉴于 {{js->clj}} 是通过 Java Script 对象递归的,Java Script 对象通常包含除厨房水槽之外的所有内容,因此这本质上是一种尽力而为的努力,而不是高原则。一句话,这里不是争辩的地方。如果集合不可清空,我希望 {{js->clj}} 努力保持顺序但不保留类型:使用向量!

5 答案

0

评论由:rohitaggarwal

(链接:~pbwolf) 您能给出一个具体的失败案例吗?

0

评论由:jszakmeister

在这里给出一个具体的案例有点困难——这似乎只有在高级编译中才会出现。我有一个从服务器返回的示例操作尝试,如下所示:{"Br": 0, "B": 100, "P": 1000} 作为 JSON。js->clj 会遇到这个描述中提到的 "没有协议方法" 错误。我发现,如果我在这段代码之前加入下面的这段代码

`
(identical? (type x) js/Object)
(into {} (for [k (js-keys x)]

       [(keyfn k) (thisfn (unchecked-get x k))]))

`

前面加入这段代码

() (coll? x) (into (empty x) (map thisfn x)))

错误消失了——但是我不确定这是否正确。我怀疑这些键再次与已知内容发生了碰撞,并且当它不是.collection的时候,某种东西被当作集合处理了。然后,当我们调用(empty x)时,由于对象没有实现所需的协议,我们失败了。

我以为这种问题以前已经被 CLJS-1658 和 7e15b1f2b894d93ef94ff86d75226f1fd3919580 解决了,但也许还有其他问题,我们又遇到了假阳性。

0

评论者:thheller

这很可能无法修复,否则会破坏其他人 js→clj 的语义。至少我无法想到简单的方法。

这里是一个简短的再现发生情况的例子

  • coll? 检查是否为 ICollection,这是一个快速路径协议
  • 快速路径协议执行一个位检查,而不是之前修复的哨兵检查
  • 位检查在一个名为 {{cljs$lang$protocol_mask$partition0$}} 的属性上执行,这个属性被 Closure 简化为未知的内容。给定你的对象中的“短”键,由于 Closure 以 a、b、c、... 开始,这种冲突的可能性非常高。

这可以在 Node REPL 中再现

`
[6:1]~cljs.user=> (def obj #js {"cljs$lang$protocol_mask$partition0$" 8})

'cljs.user/obj

[6:1]~cljs.user=> (coll? obj)
true
[6:1]~cljs.user=> (empty obj)
eval 错误 Error: No protocol method IEmptyableCollection.-empty defined for type object: [object Object]
`

一个简单的修复方法就是完全忘记 js→clj,并使用只支持 JSON 值且不使用协议的某种东西。

我写了一个可以使用示例
https://github.com/thheller/shadow-cljs/blob/master/src/main/shadow/json.cljs#L4-L37

也许我们应该在核心中添加 json→clj 并适当记录 js→clj 的问题行为?

0

评论由:jszakmeister

{quote}
也许我们应该在核心中添加 json→clj 并适当记录 js→clj 的问题行为?
{quote}

我认为这将是可取的。我在项目中对 json→clj 实现了自己的解决方案,这已经解决了这个问题一段时间了,但我想核心中的这个做法会有很大帮助。

顺便说一句,这个再现食谱很好。遗憾的是,高级编译将其缩短为可能冲突的内容。

0
参考:https://clojure.atlassian.net/browse/CLJS-2062 (由 alex+import 报告)
...