Clojure:找不到静态字段
给出以下代码:Clojure:找不到静态字段,clojure,Clojure,给出以下代码: (map Integer/parseInt ["1" "2" "3" "4"]) 除非我将Integer/parseInt包装在匿名函数中并手动调用它(#(Integer/parseInt%)),否则为什么会出现以下异常 您可能更喜欢不使用Java互操作: (地图读取字符串[“1”“2]”) 或更安全的变体: (map clojure.edn/read-string[“1”“2”]) 我个人更喜欢在Clojure代码中尽量减少Java的使用 至于为什么不能只传递Java函数,因
(map Integer/parseInt ["1" "2" "3" "4"])
除非我将Integer/parseInt
包装在匿名函数中并手动调用它(#(Integer/parseInt%)
),否则为什么会出现以下异常
您可能更喜欢不使用Java互操作:
(地图读取字符串[“1”“2]”)
或更安全的变体:
(map clojure.edn/read-string[“1”“2”])
我个人更喜欢在Clojure代码中尽量减少Java的使用
至于为什么不能只传递Java函数,因为
map
需要Clojure中的函数,而不是Java中的函数。Integer/parseInt
是Integer
类的静态方法,而不是Clojure函数。每个clojure函数都编译为java类,该类实现clojure.lang.IFn
接口map
需要clojure函数(实现IFn
接口)作为第一个参数,但是,Integer/parseInt
不是
您可以在clojure repl中检查这一点
user=> (type map)
clojure.core$map
user=> (type Integer)
java.lang.Class
user=> (type Integer/parseInt)
CompilerException java.lang.RuntimeException: Unable to find static field: parseInt in class java.lang.Integer, compiling:(/private/var/folders/p_/psdvlp_12sdcxq07pp07p_ycs_v5qf/T/form-init4110003279275246905.clj:1:1)
user=> (defn f [] 1)
#'user/f
user=> (type f)
user$f
user=> (type #(1))
user$eval9947$fn__9948
阅读可能会帮助您了解正在发生的事情。有关java interop的文档说明如下: 用于访问字段或方法成员的首选惯用格式 上面给出了一些例子。实例成员窗体同时适用于字段和 方法。对于字段和必填字段,首选instanceField表单 如果同时存在同名的字段和0参数方法。他们 所有扩展为对点运算符(如下所述)的调用 宏观膨胀时间。扩展如下: ... (类名/静态方法) args*)==>(.Classname staticMethod args*)Classname/staticField==> (.Classname静态字段) 因此,您应该记住,
Class/fieldName
只是获取静态字段的糖分,既不是静态方法调用,也不是对静态方法的引用(java方法实际上不是clojure函数),因此整数类中没有静态字段parseInt
,虽然(Class/fieldName arg)
调用一个静态方法,但它们是两个完全不同的操作,使用类似的甜语法
因此,当您执行(映射#(整数/parseInt%)[“1”“2”“3”“4]”)时,
它会扩展到
(map#(.Integer parseInt%)[“1”2“3”4])
(通过宏观扩张,您可以很容易地看到这一点)
和(映射整数/parseInt[“1”“2”“3]”)
展开为
(映射(.Integer parseInt)[“1”2“3]”)
当它试图获取一个字段(您认为是获取一个方法的引用)时失败。从Clojure(而不是Java实现)的角度考虑,您可以说map
函数的函数参数是第一个参数。听到它叫第二个参数有点困惑。@ChrisMurphy你是对的。这是一个错误。我更新了帖子。读字符串几乎总是个坏主意。文档中说:“请注意,read string可以执行代码(由read eval控制),因此只能与受信任的源一起使用。对于数据结构互操作,请使用clojure.edn/read string”。在repl(读取字符串“#=(spit\”/filename.sh\““邪恶代码”)中尝试此选项)
。由于您几乎总是对外部数据使用数据转换,读取字符串
在这里是非常不安全的,除了您已经得到的优秀答案之外-Clojure是jvm上的一个相当精简的抽象,并且没有第一类方法,因此方法不能是Clojure函数的参数。也就是说,在字节码级别上,方法不能是参数。
user=> (type map)
clojure.core$map
user=> (type Integer)
java.lang.Class
user=> (type Integer/parseInt)
CompilerException java.lang.RuntimeException: Unable to find static field: parseInt in class java.lang.Integer, compiling:(/private/var/folders/p_/psdvlp_12sdcxq07pp07p_ycs_v5qf/T/form-init4110003279275246905.clj:1:1)
user=> (defn f [] 1)
#'user/f
user=> (type f)
user$f
user=> (type #(1))
user$eval9947$fn__9948