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

欢迎!请参阅关于页面以获取更多有关该服务如何工作的信息。

+1
ClojureScript

关于在Slack的ClojureScript主题中最近的一次谈话,Dan Sutton建议我在这里创建一个问题。

我认为我可能在ClojureScript的类型推断中找到了一个Bug。我在这里创建了一个最小重现

https://github.com/paulbutcher/clojurescript-type-inference-bug

以下代码生成一个警告

  cljs.core/-, all arguments must be numbers, got [#{js/clj-nil clj-nil} #{js/clj-nil clj-nil}] instead
  (- (ocall js/Math :random) (ocall js/Math :random))
  ^---

我预期可以像这样修复它

(- ^js/number (ocall js/Math :random) ^js/number (ocall js/Math :random))

但它给我带来了完全相同的错误。

1 答案

0

被选中
 
最佳答案

^js/number 不是有效的数字提示。以 js/ 开头的任何内容都被视为externs推断的提示,因此不会影响此情况中的警告。它应该只以 ^number 的方式书写,而不需要 js 命名空间。

此外,请注意 ocall 是一个宏,因此它是否将您提供的元数据应用于源形式到输出形式取决于该宏。因此,它可能实际上并未到达需要它的编译器位置。

此外,考虑仅使用 (js/Math.random) 而不是 ocall。这将像所有标准函数一样安全地从重命名中出来。这也将正确保留类型提示。

感谢Thomas,非常感激。

为了完整性,实际上从这段代码中裁剪出来的代码调用了Vega JavaScript库中的函数:为了示例的需要,我切换到了`js.Math.random`,以避免导入Vega(过度简化的危险性!).

有没有关于这个的良善文档?我尝试过的有一件事是`^number`,得到相同的警告,并且我不知道它们之间的区别,或者类型提示对于宏不会起作用的事实?

再次感谢!
类型提示对于宏也可以正常工作,但要记住,宏是接收一个形式并返回另一个形式的函数。如果宏没有明确地将从输入接收到的元数据“转移”到输出,它将会丢失。我猜测`ocall`没有这样做,但我不确定。

在我看来,最好完全避免ocall之类的。
感谢Thomas。

如果我想真正了解这个话题(例如,了解^js/number和^number之间的区别),我应该查找哪些文档来帮助我理解呢?
我并不了解有关这个主题的任何文档。但我相信一定存在这样的文档。

简单来说,编译器只识别几种类型提示。其中正是“数字”和“布尔”类型。然后还有“js”和“js/*”,主要用于外部推断,告诉编译器收集外部声明以保护在:高级编译中防止重命名。

真正区别在于它需要一个完全匹配,而“数字”不等于“js/number”。
by
太好了。感谢您的帮助——非常感激。
...