Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure:找不到静态字段_Clojure - Fatal编程技术网

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