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

欢迎!请查看 关于 页面以了解更多关于这是如何工作的信息。

0
ClojureScript
{{js->clj}} 表明:


  (cond

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


这里的问题在于 {{(coll? x)}} 检查的是 ICollection,而 {{(empty x)}} 需要的是 IEmptyableCollection。当 x 通过了第一个测试但第二个测试失败时,{{js->clj}} 会抛出 "Error: 没有定义针对类型 : [object Object]" 的协议方法 IEmptyableCollection.-empty。"  

由于 {{js->clj}} 是通过 JavaScript 对象递归的,而 JavaScript 对象倾向于包含所有东西,除了厨房用具,所以这最终成为了一个尽力而为的问题,而不是一个原则性很强的任务。一句话,这不是吹毛求疵的地方。如果集合不可为空,我期望 {{js->clj}} 尽力维护顺序但不是类型:使用一个 vector 试试!

5 个答案

0

评论由:rohitaggarwal 发表

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

0

评论由:jszakmeister 发表

在这里给出一个具体的案例很难——这好像只有在编译的高级阶段才会出现。我有一个从服务器返回这样的例程,类似于这个:"Br": 0, "B": 100, "P": 1000",作为 JSON。js->clj 会触发描述中提到的 "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)
eval错误Error:对于类型object:[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(由alex+import报告)
...