2024 Clojure状态调查!中分享您的想法。

欢迎!关于这个工作的更多信息,请查看关于页面。

+1
编译器

在实现Cursive对新的函数式接口转换功能的支持时,我发现Java和Clojure在这方面存在一些不一致性。我想检查这些不一致性是故意的还是无意为之。

  1. Clojure要求包含SAM(单一抽象方法)的类必须有一个FunctionalInterface注解才能具备转换的资格。然而,Java没有这种限制,JLS也没有提到这一点:https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.8。这可能会产生问题,因为在库中可能存在没有该注解的类,这些类可以用Java的lambda表达式使用,但在Clojure中不能。这很容易发生在一些旧的预lambda库中的类上。似乎FunctionalInterface更多的是为了确保一个接口有意成为SAM,并且不会意外地添加到它的方法中(https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.6.4.9)。实际上,该部分明确指出,该注解不是使接口函数化的必需条件。
  2. 同样,规范说明函数式接口必须是一个接口,但Compiler.FISupport.maybeFIMethod()并没有检查这一点,它只检查方法本身是否是抽象的。因此Clojure会接受包含SAM的抽象类,但Java不会。这一条在实际应用中可能不太可能发生,但也很容易改进,我看不出不执行此操作有什么有用的情况。

2 条回答

0
by
谢谢,我之前没看过这个。不幸的是,这个问题不会在1.12版本中修复,这可能会影响到人们。

无论如何,我想我会实现编译器当前的做法。
0
by
编辑 by

1)我们的目标是在Clojure函数与Java构造之间找到语义匹配的地方,并使它们在这个地方的使用变得隐式。标有此类标记的功能接口必须只有一个方法,并明确表达了这种意图。虽然SAM接口在结构上相似,但没有这种明确的意图,也可能不与Clojure函数在语义上匹配(而是“过程”或其他非功能性概念)。

尽管如此,SAM和方法值组合是一个有趣的交集点,我们仍在研究该点。如果你向接受SAM的方法传递方法值,那是一个我们可以直接适应(就像Java使用方法引用)而不创建方法值包装器并适应此点的地方。这是一个没有Clojure函数且不需要语义匹配的使用案例,我们可以支持这一点,还待定。

2)maybeFIMethod检查类是否有@FunctionalInterface注解,这只能存在于接口中,因此检查是否为接口是冗余的。

...