试图将java成员函数作为var传递

kor*_*tyi 3 clojure

如果我在REPL中运行以下代码

(let [f '.startsWith] (f "abab" "a"))
Run Code Online (Sandbox Code Playgroud)

它被评估为"a"而不是"true".有人可以解释一下这个令人惊讶的结果吗?

实际上,真正的代码,我想做的工作如下.

(defn set-up-bean! [bean functions-and-parameters]
  (doseq [[f p] functions-and-parameters]
    (f bean p))
  (.init bean))
Run Code Online (Sandbox Code Playgroud)

我想要实现的是,使以下两个函数调用做同样的事情.

(set-up-bean! bean [['.setMember "a"]])
Run Code Online (Sandbox Code Playgroud)

(do
  (.setMember bean "a")
  (.init bean))
Run Code Online (Sandbox Code Playgroud)

Cha*_*ffy 6

一种传统方法是使用匿名函数

(let [f (fn [a b] (.startsWith ^String a ^String b))] (f "abab" "a"))
Run Code Online (Sandbox Code Playgroud)

...因为这允许您根据需要键入提示参数.你也可以考虑memfn:

(let [f (memfn startsWith String)] (f "abab" "a"))
Run Code Online (Sandbox Code Playgroud)

无论如何 - 点符号是互操作的语法糖,而不是提供真正的可调用函数.

  • 更准确一点,你可能会说`(.startsWith ...)`是`(.startsWith ...)`的语法糖,而`(....)`是一种特殊形式,而不是功能.你不能在变量中存储一个特殊的形式,并从那里"调用"它,就像你不能将宏存储在变量中并"调用"它一样.一个特殊的形式告诉编译器"在这里生成一些特殊代码而不是函数调用的常规代码". (5认同)