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不支持在字符串上使用>运算符,这就是为什么总是出现错误。

by
谢谢你的快速回答,尤金!很有道理,但这是否解释了为什么评估表达式`(> "A" "B")`返回nil?我觉得这并不重要,但这种不一致似乎很奇怪。我同意只对数值类型使用>等操作符,尽管它在JavaScript运行时确实有效。

I
by
我认为这是因为对除了数值类型以外的任何东西使用`>`是不确定的操作模式。哦,并且在我的情况下,它在我基于Node的REPL中返回预期的布尔值。
...