3

考虑.indexOf函数。(.indexOf [1 2 3] 2)我知道如果我只需要立即使用该功能,我可以调用。但是,如果我想将函数作为参数传递给其他函数(例如 map)怎么办?以下不起作用,返回 CompilerException “无法解析符号”:

(map .indexOf [[1 2 3] [4 5 6]] [2 4])

显然,我可以.indexOf在一些匿名函数内部包装一个调用以达到相同的效果:

(map #(.indexOf %1 %2) [[1 2 3] [4 5 6]] [2 4])

但这不是我要问的。是否有另一种方式来引用.indexOf这样的包装函数不是必需的?如果这是不可能的,是否有充分的理由不支持它?

4

5 回答 5

5

Clojure 函数是 IFn 接口的实例,这意味着它们可以被调用。另一方面,java 方法不实现接口,不能用作高阶函数。

正如 Alister Lee 所指出的,您可以使用 memfn 来包装方法调用。但是,如果您检查文档,您会发现您提到的匿名函数方法是执行您要求的首选方法。

于 2013-10-16T13:58:56.323 回答
3

首先.indexOf不是函数。片段

(.indexOf [1 2 3] 2)

或等效形式

(. [1 2 3] indexOf 3)

称为点特殊形式。特殊形式的评估规则与函数应用程序的规则不同。在这种情况下,特殊规则是第一个参数被视为目标对象,第二个参数(如果是符号)被假定为目标对象上的方法或字段。现在,很清楚为什么.indexOf不是有效的符号或函数。

你是对的,我们可以用一等函数包装成员访问并在map方法中使用它。正如上面提到的 Alister Lee 所说,memfn为此目的很方便:

(map (memfn indexOf elem) [[1 2 3] [4 5 6]] [2 4])
于 2013-10-16T14:02:23.370 回答
1

Java 方法并非设计为一流的函数。它们的行为不像一流的函数,也不像它们那样实现。在没有类的情况下传递 java 方法并没有多大意义。

因此,Clojure 可以成为一种函数式语言,它创建了一流的函数,这些函数旨在在不需要拥有类的情况下使用和传递(在实现方面它们是单例类,因为我们必须使用 JVM 的事物模型用于实施)。

如果我们试图让 Java 方法表现得像 clojure 的第一类函数,我们将不得不为我们的函数提供一个不那么强大的基础(降低函数的门槛,使其真正表现得像方法),或者一堆乏味的特殊情况异常记住方法函数与实际函数。决定我们最好承认方法从来都不是真正的函数,而不是像对待它们一样对待它们。特别是当在函数中包装对方法的调用非常容易时(如您所示)。

于 2013-10-16T13:58:29.087 回答
0

只有一个澄清

“.indexOf”不完全是一个函数,而是一个“点”加上一个“名称函数或instanceMember”。我的意思是,在这种情况下的函数是 this 元素的联合,因此您的“名称函数”需要将实际函数上下文化的 java 对象。

祝娟好运

于 2013-10-16T11:45:14.500 回答
0

我不知道 - 但不应该

(def j-fn #(.indexOf %1 %2))
(j-fn "foox" "x")
;=> 3

几乎做你所期望的?基本上将其包装在 anon-fn 中

于 2013-10-16T21:50:04.707 回答