评论者:ajoberstar
这里是一个替代方法,在我的(ike.cljj)库中(链接:[https://github.com/ajoberstar/ike.cljj/blob/master/src/main/clojure/ike/cljj/function.clj](https://github.com/ajoberstar/ike.cljj/blob/master/src/main/clojure/ike/cljj/function.clj))。它使用MethodHandles(即java.lang.invoke包)而不是常规反射。我还不确定是否在抽象类上测试了这种方法。
使用方法与Ghadi帖子中的类似
`
(defsam my-sam
java.util.function.Predicate
[x]
(= x "it matched"))
(-> (Stream/of "not a match" "it matched")
(.filter my-sam)
(.collect Collectors/toList)
(-> (IntStream/range 0 10)
(.filter (sam* java.util.function.IntPredicate odd?))
(.collect Collectors/toList)
`
它使用MethodHandleProxies.asInterfaceInstance来创建一个代理实例的接口,该接口调用一个方法处理程序调用Clojure函数。它不会尝试验证参数数量,只是将它作为varargs委托给IFn.applyTo(ISeq)。不确定这是否最有效,但对我来说它是有效的。
我认为LambdaMetaFactory可能是满足此类用例的首选方式。但我很难确切地了解如何使用它,所以我没有深入研究。
我在这种方法(以及Ghadi的)中的主要功能性问题是,你必须显式提供要代理的接口。Java lambdas和Groovy Closures可以用于期望SAM的方法,它只是根据方法期望的进行强制转型。理想情况下,Clojure也应该支持这种功能。
而不是这样做:
`
(-> (IntStream/range 0 10)
(.filter (sam* java.util.function.IntPredicate odd?))
(.collect Collectors/toList)
`
我希望这样做:
`
(-> (IntStream/range 0 10)
(.filter odd?)
(.collect Collectors/toList)
`