如何在Clojure中将静态方法传递给comp函数?

24

看起来我在使用comp时无法访问Integer.parseInt。我可以通过以下方式正常访问:

user=> (Integer/parseInt "123")
123

但是如果我把它放在comp里,就会出现错误:

user=> (def vect-to-int (comp Integer/parseInt (partial apply str)))
java.lang.Exception: Unable to find static field: parseInt in class java.lang.Integer (NO_SOURCE_FILE:3)

我觉得它似乎在尝试查找Integer上的字段,而应该寻找一个方法。我该如何像这样使用Integer.parseInt?是否有更好的方法将字符向量转换为int

2个回答

29

Clojure函数是Java方法,但Java方法不是Clojure函数。例如,Clojure函数具有元数据等特性。如果您想在需要调用Clojure函数的地方使用Java方法,则有两种封装它的选择:memfnfun或#()memfn是一个过时的函数,将Java方法封装到Clojure函数中(即使不经常使用,了解其存在也很有好处)。通常接受的包装Java方法的方式是:

#(. instance method arg1 argN)  
或者对于静态方法。
#(Class/MethodName arg1 argN)

我猜第一句话并不严格正确,但它确实表达了要点 :) - Arthur Ulfeldt
我认为你是想说 fn 而不是 fun? - Didier A.

7
(def vec-to-int (comp #(Integer/parseInt %) (partial apply str)))

或者

(def vec-to-int #(Integer/parseInt (apply str %)))

partialcomp在Clojure中通常不如使用#()来创建匿名函数简洁。个人而言,我会这样写:

(defn vec-to-int [x] (Integer/parseInt (apply str x)))

你可以使用普通的def来实现这个,但是相较于defn,你真正获得了什么?使用def会掩盖你正在定义一个函数的事实。而defn还为您设置了额外的元数据(arglists),而def则没有。
无论如何,这是一种更通用的方法来实现你所做的事情:
(def vec-to-int #(bigint (apply str %)))

并且更加通用:

(def vec-to-int #(read-string (apply str %)))

这取决于您是否想处理除整数以外的其他事情。


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