Clojure:将 def 转换为 Java 静态函数

4
考虑以下Clojure代码:
(defn space? [c] (Character/isWhitespace c))

这没关系。但是显然,这只是另一个毫无意义的重命名和重构:

(def space? Character/isWhitespace)

但是我遇到了编译错误:
Caused by: java.lang.RuntimeException: Unable to find static field: isWhitespace 
in class java.lang.Character

为什么它找不到呢?使用Clojure函数时它可以完美运行:

(def wrap-space? space?) ; Compiles OK!

这里发生了什么?为什么在Java静态函数中使用def不起作用?

如果你真的想使用 def,那么你必须使用匿名函数:(def space? #(Character/isWhitespace? %)) - Alex
@Alex,这仍然不是我想要的无点符号表示法。我也考虑过这个变体,谢谢。 - demi
1个回答

7

你的前两个语句实际上并不等价。当你说...

(def space? Character/isWhitespace)

...Clojure 正在尝试查找名为 isWhitespace 的静态字段(而不是方法)在 java.lang.Character 中。当然,这样的字段不存在,这就是为什么会出现编译错误的原因。

其他正确的重写以下语句的方式...

(defn space? [c] (Character/isWhitespace c))

...将是:

  • (def space? (fn [c] (Character/isWhitespace c)))
  • (defn space? [c] (. Character isWhitespace c))

编辑

只是补充一下,我想Clojure允许(def wrap-space? space?)的原因是因为space?是没有歧义的。然而,一个静态的Java方法可能会有不同的参数集重载,或者与一个静态字段共享相同的名称。因此,要为静态的Java方法设置别名,必须明确指定您要设置别名的方法/字段。


编辑功能非常有用。不过,我认为最好提供关于歧义的错误信息。这样更清晰明了。 - demi
1
由于存在歧义的可能性,除非在调用位置,否则它甚至不会寻找方法。虽然我同意Clojure的错误通常不太有帮助。我认为语义上的区别在于所有Clojure函数都是对象,而方法附加到其他某些对象上,虽然我们喜欢将事物视为一等公民,但没有理由将某些东西视为一等公民,因为(像Java方法一样)它不是一等公民,不能独立存在。 - noisesmith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接