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

欢迎!请参阅关于页面了解更多关于该网站如何工作的信息。

0
ClojureScript
{{js->clj}} says


  (cond

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


问题是({{(coll? x)}})检查的是ICollection,而({{(empty x)}})需要IEmptyableCollection。当x通过第一个测试但未通过第二个测试时,{{js->clj}}会抛出"Error: No protocol method IEmptyableCollection.-empty defined for type : [object Object]."  

由于{{js->clj}}会递归地遍历可能含有任何内容的JavaScript对象,因此这只能是尽力而为的事,而不是原则性的事。总的来说,这里不是吹毛求疵的地方。如果集合不能为空,我期望{{js->clj}}尽可能保持顺序,但不是类型:使用vector

5 答案

0

评论人:rohitaggarwal

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

0

评论人:jszakmeister

在这里很难给出具体的案例——看起来这只有在高级编译时才会出现。我有一个从服务器返回的例程,类似于这样:{"Br": 0, "B": 100, "P": 1000},作为JSON。js->clj会在generate "no protocol method" 错误。我发现,如果我把这个片段

`
(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))

错误消失了——但我不知道这是否是正确的做法。我怀疑键又与已知的东西发生了某种形式的碰撞,并且某些东西被错误地处理为集合。然后,当调用(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)
评估错误 Error:未在类型对象 [object Object] 上定义 IEmptyableCollection.-empty 协议方法
`

一个简单的修复方法是忘记使用 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(亚历克斯+导入报告)
...