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
谢谢你的快速回答Eugene!有道理,但是这解释了为什么评估表达式`(> "A" "B")`返回nil吗?我认为这并不重要,但看起来不一致。我同意仅对数值类型使用>等运算符,尽管在JS运行时它也有效。

I
by
我相信,使用`>`对非数值类型进行操作是未定义的行为。哦,在我的情况下,在基于Node的REPL中返回预期的布尔值。
...