库函数与Clojure中的Java方法

Mar*_*ark 7 java function clojure

在阅读"Programming Clojure"时,我注意到在Clojure中有其他方法可以执行某些操作.例如,假设我们需要将字符串的所有字符转换为大写的变体.

我们可以使用.toUpperCase:

user> (.toUpperCase "foo")
;; => "FOO"
Run Code Online (Sandbox Code Playgroud)

以及clojure.string/upper-case:

user> (clojure.string/upper-case "foo")
;; => "FOO"
Run Code Online (Sandbox Code Playgroud)

虽然clojure.string/upper-case是一个功能,我们可以这样对待它:

user> (map clojure.string/upper-case ["foo" "bar" "baz"])
;; => ("FOO" "BAR" "BAZ")
Run Code Online (Sandbox Code Playgroud)

......我们不能这样做.toUpperCase:

user> (map .toUpperCase ["foo" "bar" "baz"])
CompilerException java.lang.RuntimeException: Unable to resolve symbol...
Run Code Online (Sandbox Code Playgroud)

我想这.toUpperCase是Java方法的直接调用,而Clojure知道如何处理这个符号,当它是表单的第一个元素时.

:我应该使用什么.toUpperCase或者有clojure.string/upper-case什么区别:

(map clojure.string/upper-case ["foo" "bar" "baz"])
Run Code Online (Sandbox Code Playgroud)

(map (fn [x] (.toUpperCase x)) ["foo" "bar" "baz"])
Run Code Online (Sandbox Code Playgroud)

mik*_*era 7

两者都有效:它基本上是一个权衡如下:

包装Clojure功能的优点:

  • 更具惯用性的Clojure风格
  • 更容易携带(例如ClojureScript)
  • 可以传递给更高阶的函数

使用Java方法的优点:

  • 性能略好(假设您正确使用类型提示以避免反射)
  • 如果您正在使用Java程序员/ Java代码库,则更加透明

通常情况下,我更喜欢使用包装的Clojure函数,除非我已经对基准测试并确定了性能问题,此时我可能会直接使用Java互操作.


nta*_*lbs 6

clojure.string/upper-case只是java.lang.String.toUpperCase方法的包装函数.您可以在您的repl中办理登机手续.

user=> (source clojure.string/upper-case)
(defn ^String upper-case
  "Converts string to all upper-case."
  {:added "1.2"}
  [^CharSequence s]
  (.. s toString toUpperCase))
Run Code Online (Sandbox Code Playgroud)

如您所见,upper-case只需调用即可toUpperCase.

我不认为有任何强有力的规则只选择他们之间的一个.但是,正如您所知,.toUpperCasemethod不是clojure函数,不能作为参数传递给其他高阶函数.因此,clojure.string/upper-case如果您没有任何具体的理由使用.toUpperCase方法,最好使用.