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

欢迎!请查看关于页面获取更多信息。

0投票
ClojureScript

当在CLJS中构建自定义比较函数时,我遇到了一些在我看来很奇怪的行为。

当在REPL中直接使用>(或类似)函数比较两个字符串时,我会收到一个:invalid-arithmetic警告,并返回nil(类似于CLJ抛出异常)。当我这样做时,函数内部则不会收到任何警告,它将返回一个布尔值(CLJ抛出异常)。

CLJS

clj꞉user꞉> (> "A" "Z")
nil
; ------ WARNING - :invalid-arithmetic -------------------------------------------
;  Resource: <eval>:1:1
 cljs.core/>, all arguments must be numbers, got [string string] instead
--------------------------------------------------------------------------------

clj꞉user꞉> ((fn [x y] (> x y)) "A" "Z")
false

CLJ

user=> (> "A" "Z")
Execution error (ClassCastException) at user/eval3 (REPL:1).
class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')
user=> ((fn [x y] (> x y)) "A" "Z")
Execution error (ClassCastException) at user/eval5$fn (REPL:1).
class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')

有人能解释发生了什么吗?

谢谢,
Julian

1回答

+2投票

选中
 
最佳回答

WARNING - :invalid-arithmetic来自CLJS的分析器,该分析器在代码编译期间运行。当它可以确定参数的类型,并且这些类型不是数字时,它会发出警告。当它无法确定,例如在函数示例中,它将保持沉默。

并且它不会导致运行时错误,因为底层平台JavaScript允许这样做。但您仍应使用ClojureScript的>操作符,因为它是设计为算术操作的。

在CLJ中,底层平台JVM不支持在字符串上使用> - 这就是为什么这始终是一个错误。

谢谢你快速回答,Eugene!听起来很有道理,但这是否解释了为什么评估表达式`(> "A" "B")`返回nil?我认为这并不是很重要,但似乎不太一致。我同意只有对数字类型使用>等,即使在JS运行时它也可以工作。

I
我相信这是因为在除了数字类型之外的任何类型上使用`>`是未定义的行为。哦,还有,在我的情况下,在基于Node的REPL中它返回预期的布尔值。
...