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的接口继续保持为SAM,而不会意外添加方法(《https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.6.4.9》))。实际上,该部分明确指出,注解对于接口是功能性的不是必需的。
  2. 同样,规范表示功能接口必须是一个接口,但Compiler.FISupport.maybeFIMethod()并没有检查这个,它只检查了方法本身是抽象的。所以Clojure会接受包含SAM的抽象类,但Java不会。这种情况在实际中似乎不太可能发生,但也很容易解决,我没有看到不执行此检查的有用用例。

2 答案

0
谢谢,我没看到这个。很遗憾,这将在1.12中不会修复,这似乎很可能会影响到人们。

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

编辑

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

话虽如此,SAM和方法值组合是一个有趣的汇聚点,我们仍在努力解决。如果你将一个方法值传递给接收SAM的方法,那是一个我们可以直接适应(就像Java使用方法引用那样)的点,而不需要创建方法值包装器并对其进行调整。这是一个没有Clojure函数也没有语义匹配需求的使用场景,我们可能仍然会支持这个,还有待确定。

2) maybeFIMethod检查类是否有@FunctionalInterface注释,这只能在接口上存在,因此检查它是否是接口是多余的。

...