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 会抛出 "错误:未定义类型为 : [object Object]" 的协议方法 IEmptyableCollection.-empty。" 

由于 js->clj 是通过 Javascript 对象进行的递归,这些对象往往包含除了厨房水槽之外的一切,因此这注定是一个尽力而为而不是原则性强的过程。换句话说,这不是细枝末节的地方。如果集合不可为空,我期望 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))

错误消失了——但我不知道这是否是正确的做法。我怀疑键 somehow 再次与前知事项发生冲突,某事物不是集合却被当作集合处理。然后,当调用 (empty x) 时,由于对象未实现所需协议,我们失败了。

我以为这种情况已经被 CLJS-1658 和 7e15b1f2b894d93ef94ff86d75226f1fd3919580 解决了,但也许我们又遇到了假阳性。

0

评论者:thheller

这可能是无法修复而不破坏其他人 js->clj 语义的问题。至少我想不出任何简单的解决方案。

以下是一个简短的发生实例

  • coll? 检查 ICollection,这是快速路径协议
  • 快速路径协议会做一点检查,而不是之前固定下来的哨兵检查
  • 位检查是在一个命名为 {{cljs$lang$protocol_mask$partition0$}} 的属性上进行的,这个属性被 Closure 缩短到了一个未知的内容。考虑到你例子中的 Object 的 "简短" 键,在 Closure 以 a、b、c、... 开始的情况下,这是非常可能发生冲突的。

This can be reproduced in the 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 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

也许我们应该在 core 中添加 json->clj 并正确记录 js->clj 的问题行为?

0

由 jszakmeister 发表的评论

{quote}
也许我们应该在 core 中添加 json->clj 并正确记录 js->clj 的问题行为?
{quote}

我认为这很建议。我之前在我的项目中实现了自己的 json->clj 来解决这个问题,但我认为在 core 中这样做会有很大益处。

顺便提一下,很遗憾编译后将其缩短为可能会导致冲突的内容。

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