评论者:ajoberstar
以下是在我(链接:[ike.cljj 库](https://github.com/ajoberstar/ike.cljj/blob/master/src/main/clojure/ike/cljj/function.clj) 文本:ike.cljj)中的一种替代方法。它使用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](https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandleProxies.html#asInterfaceInstance-java.lang.Class-java.lang.invoke.MethodHandle-) 文本)来创建一个代理实例,该实例通过调用Clojure函数的方法句柄调用接口。它不尝试验证参数数量,只是将其视为varargs,委托给IFn.applyTo(ISeq)。不确定这是否是最有效的方式,但对我来说是有效的。
我认为(链接:[LambdaMetaFactory](https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/invoke/MethodHandles.html) 文本)可能是满足这类使用需求的最佳方式。但是,对我来说,跟随它确实更难,所以我最终没有深入研究它。
我对我的方法(以及Ghadi的方法)的主要功能问题是您必须显式提供要代理的接口。Java lambda和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)
`