在 clojure 中取消引用 java 方法

Unquote a java method in clojure

如何在 Clojure 中参数化调用方法?

示例:

(def url (java.net.URL. "http://www.google.com"))
(.getHost url) ;; works!
(def host '.getHost)
(host url) ;; Nope :(
(~host url) ;; Nope :(
(eval `(~host url)) ;; Works :s

如果您只是想为现有函数创建一个别名,您只需要一个包装函数:

> (ns clj (:import [java.net URL]))
> (def url (URL. "http://www.google.com"))
> (defn host [arg] (.getHost arg))
> (host url)
;=> "www.google.com"

虽然您可以像其他用户指出的那样使用 memfn,但发生的事情似乎不太明显。事实上,现在甚至 clojure.org 都反对它:


https://clojure.org/reference/java_interop

(memfn method-name arg-names)*

Macro. Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn.

(map (memfn charAt i) ["fred" "ethel" "lucy"] [1 2 3])
-> (\r \h \y)

Note it almost always preferable to do this directly now, with syntax like:

(map #(.charAt %1 %2) ["fred" "ethel" "lucy"] [1 2 3])
-> (\r \h \y)

使用memfn:

(def url (java.net.URL. "http://www.google.com"))
(def host (memfn getHost))
(host url)

在 Java class 上参数化方法的正常方法是:

#(.method fixed-object %)

#(.method % fixed argument)

或者如果对象或参数都不固定。

#(.method %1 %2)

经常与高阶函数line map、filter和reduce一起使用。

(map #(.getMoney %) customers)

正确解:

(def url (URL. "http://www.google.com"))
(def host 'getHost)
(defn dynamic-invoke
  [obj method arglist]
  (.invoke (.getDeclaredMethod
             (class obj) (name method) nil)
           obj (into-array arglist)))
(dynamic-invoke url host [])