2024年Clojure调查问卷中分享你的看法!

欢迎!请查阅关于页面以了解该网站如何运作的相关更多信息。

+1
ClojureScript

在Slack的ClojureScript主题中最近的讨论之后,Dan Sutton建议我在这里创建一个issue。

我认为我可能在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之间的区别),我应该看哪些文档才能帮助我理解?
我不了解有关这方面的任何文档。我相信一定有。

简单来说,只有几个类型提示是编译器可以识别的。有“number”和“boolean”正是为此。还有“js”和“js/*”用于外部推断,基本上告诉编译器收集外部声明以避免在:advanced编译中的重命名。

真正区别在于它们需要准确匹配,“number”不等于“js/number”。
太好了。非常感谢您的帮助。
...