在clojure中,如何在不立即调用时引用java函数?

时间:2013-10-16 07:27:46

标签: java clojure

考虑.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,这样就不需要包装函数了?如果这是不可能的,有没有理由不支持这个?

5 个答案:

答案 0 :(得分:5)

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

正如Alister Lee指出的那样,你可以使用memfn来包装方法调用。但是如果你检查 documentation,你会发现你提到的匿名函数方法是你要求的首选方法。

答案 1 :(得分:2)

首先.indexOf不是函数。摘录

(.indexOf [1 2 3] 2)

或等效表格

(. [1 2 3] indexOf 3)

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

你是对的,我们可以使用第一类函数包装成员访问,并在map方法中使用它。正如Alister Lee上面提到的那样,memfn对于这个目的很方便:

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

答案 2 :(得分:1)

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

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

如果我们试图让Java方法像clojure的第一类函数一样,那么我们必须为函数提供一个不那么强大的基础(降低函数的标准,使它们真的像方法一样),或者一堆繁琐的记忆方法功能与实际功能的特殊情况例外。我们做出的决定是,我们最好承认方法从来就不是真正的功能,而不是像对待它们那样对待它们。特别是当一个函数中的方法调用很容易时(如你所示)。

答案 3 :(得分:0)

只有一个澄清

“。indexOf”不是一个函数,而是一个“点”加上“name function或instanceMember”。我的意思是在这种情况下函数是这些元素的并集,所以你的“名称函数”需要java对象,它将实际函数的上下文化。

祝你好运 涓

答案 4 :(得分:0)

我不知道 - 但不应该

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

你真的按照自己的意愿行事吗? 基本上将它包装在anon-fn