My use case isn't a particularly great one at that minute. It mainly just
seemed like an unfortunate extra step to interacting with Java APIs.

Essentially, I was trying to leverage APIs that return a Java Stream, but
wanted to interact with them with Clojure goodness, like
map/reduce/transduce. I ended up extending CollReduce to support
BaseStream. The lambda interaction is a pretty minimal portion of that
code, being a little more heavy in the supporting tests.

Most of my interest is projecting into the future and presuming that more
Java APIs will expect SAM arguments. If that is the case, it seems like a
beneficial thing to support in Clojure. Though it depends on the impact to
the compiler. I can see the argument either way.

Andrew Oberstar

On Mon, Jul 27, 2015 at 9:49 PM Sean Corfield <s...@corfield.org> wrote:

> I think Mike was suggesting something like this:
>
> (-> (IntStream/range 0 100) (.filter ^Predicate odd?) (.limit 5) (.collect
> Collectors/toList))
>
> and having the Clojure compiler figure out that you’re trying to cast an
> IFn to a functional interface and therefore "do the magic" for you. I don’t
> know whether this is even feasible (FWIW, I certainly don’t think it is
> desirable).
>
> The compiler would have to know about all the possible functional
> interfaces in order to reify them behind the scenes for you (since each one
> has a different method name, so something needs to know how to get from the
> Java interface type to the method name behind it).
>
> I’m not sure I "get" your use case — if you’re dealing with that much Java
> interop it seems like it might be a good idea to create a DSL (functions,
> maybe macros) that make the code cleaner and "hide" the low-level details
> of Java interop anyway. Besides, your example sounds like something Clojure
> can already do natively and much more cleanly. Can you perhaps give us more
> detailed motivation for what you’re trying to achieve? Perhaps there’s a
> cleaner way altogether…?
>
> Sean
>
> On Jul 27, 2015, at 6:53 PM, Andrew Oberstar <ajobers...@gmail.com> wrote:
>
> Mikera, I think you're addressing a different interop concern. I'm
> particularly interested in something like this:
>
> (-> (IntStream/range 0 100) (.filter odd?) (.limit 5) (.collect
> Collectors/toList))
>
> Where "odd?" is a normal Clojure IFn that I want to use when calling a
> Java API that expects something implementing a single-method-interface
> (Predicate in this case).
>
> Right now I need to do something like this:
>
> (defn lambda [f] (reify Predicate (test [x] (f x))))
>
> (-> (IntStream/range 0 100) (.filter (lambda odd?)) (.limit 5) (.collect
> Collectors/toList))
>
> Andrew Oberstar
>
>
> On Mon, Jul 27, 2015 at 8:16 PM Mikera <mike.r.anderson...@gmail.com>
> wrote:
>
>> It could certainly be achieved in the Clojure compiler, by allowing
>> (some-functional-interface .....) to compile to the appropriate function
>> call even if it doesn't implement IFn
>>
>> It would be quite a big change though and would probably have some
>> limitations, e.g.:
>> a) It probably wouldn't work with regular vars since it wouldn't be able
>> to handle re-binding
>> b) You would probably have to type hint the "some-functional-interface"
>> object in some way so that the compiler knows to do this at compile time
>>
>> A less invasive option would be to just have some code to wrap functional
>> interfaces in an appropriate IFn.
>>
>> Worth a JIRA ticket for consideration at least?
>>
>>
>>
>> On Tuesday, 28 July 2015 08:52:47 UTC+8, Andrew Oberstar wrote:
>>
>>> Thanks for the reply Gary. Sounds like I'm on as good a track as I can
>>> be with current Clojure.
>>>
>>> I am curious though why you say that it is unrealistic for IFn to
>>> support arbitrary @FunctionalInterface. It certainly seems like it would
>>> require compiler changes, but I would think that either through emitting
>>> bytecode closer to Java 8 lambdas or through some form of type coercion it
>>> would possible. For example, Groovy just coerces their Closures to any
>>> Single Abstract Method type.
>>>
>>> I'm not sure how java.util.function.* as protocols would work, but still
>>> would require implementing for each SAM you come across. IFn as a protocol
>>> seems to address a different interop use case. Maybe for receiving a Java
>>> lambda you want to use as if it's a Clojure function.
>>>
>>> Most of the Java interop from Clojure is slick (sometimes more clear
>>> than in Java itself), it would be unfortunate to leave functions as
>>> second-class citizens for interop. Granted, there may be a simplicity
>>> argument against this (maybe that's why Java varargs require an explicit
>>> array?).
>>>
>>> Andrew Oberstar
>>>
>>> On Mon, Jul 27, 2015 at 4:16 AM Gary Verhaegen <gary.ve...@gmail.com>
>>> wrote:
>>>
>>>> On Sunday, 26 July 2015, Andrew Oberstar <ajobe...@gmail.com> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> I'm wondering if anyone has a good approach for making calls from
>>>>> Clojure to Java APIs (e.g. Stream API) that expect a @FunctionalInterface
>>>>> type.
>>>>>
>>>>> Ideally, IFn would transparently work, but I'm guessing that requires
>>>>> some compiler changes.
>>>>>
>>>>> Right now, the best I can think of is a function or macro to reify a
>>>>> wrapper around a Clojure function to implement all of the usual interfaces
>>>>> from java.util.function.
>>>>>
>>>>> Anyone have any better ideas?
>>>>>
>>>>> Andrew Oberstar
>>>>>
>>>>
>>>> You're probably aware of this, but @FunctionalInterface is not a type,
>>>> it's an annotation. All it does is ensure, at compile time, that the
>>>> annotated element is an interface with a single non-default and non-static
>>>> method. At the type-system level, it's just an interface like any other,
>>>> and the lambda syntax is just a shorthand for an anonymous instance of a
>>>> well-defined type.
>>>>
>>>> Since the lambda syntax is java-compiler magic, you can't access it
>>>> from Clojure, and the most straightforward option right now is to actually
>>>> know which type is expected, e.g.:
>>>>
>>>> user=> (-> (doto (java.util.ArrayList.) (.add 1) (.add 2)) (.stream)
>>>> (.map (reify java.util.function.Function (apply [_ arg] (inc arg))))
>>>> (.collect (java.util.stream.Collectors/toList)))
>>>> [2 3]
>>>> user=>
>>>>
>>>> As neither IFn nor Function are Clojure protocols, I do indeed think
>>>> you're best bet is a macro to essentially generate the above reify. You can
>>>> of course do a single macro that reifies to all of the protocols that you
>>>> need.
>>>>
>>>> I don't think it's realistic to hope that IFn will cover any arbitrary
>>>> @FunctionalInterface, as that is Java compiler magic. It may, in the
>>>> future, be extended to cover all of the standard ones in
>>>> java.util.function, or even all the ones in the standard library, but it's
>>>> not going to happen until Java 7 support is dropped. I guess the best you
>>>> could hope for in the short term would be to have IFn changed to a 
>>>> protocol.
>>>>
>>>
>
>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to