Here are two alternatives that should work right now:

UnaryOperator<Integer> multiplier(int multiplicand) {
  return x -> x * multiplicand;
}

List<Integer> list = [1, 2, 3]

list.collect(multiplier(2)) // fails

list.collect(multiplier(2).&apply)

list.collect(this.&miltiplier.curry(2))


-----Original Message-----
From: Milles, Eric (TR Technology) <eric.mil...@thomsonreuters.com> 
Sent: Wednesday, April 28, 2021 12:07 PM
To: dev@groovy.apache.org
Subject: RE: GDK retrofit for Java functional interfaces

It is best IMO to open a JIRA ticket first so that discussion and metadata can 
be tracked.  Beyond that, opening a pull request on github with a link back to 
the ticket should suffice.  The ticket prevents surprise when a pull request 
shows up.  And I'd suggest starting with a small change first.

-----Original Message-----
From: Christopher Smith <chry...@gmail.com>
Sent: Wednesday, April 28, 2021 11:36 AM
To: dev@groovy.apache.org
Subject: Re: GDK retrofit for Java functional interfaces

My case for `with` and `tap` is that in both cases they're immensely useful as 
general pipeline operations, and being able* to use `with(Foo::transform)` but 
not `with(Foo.transform(param))` is inconsistent and has been an in-real-use 
frustration for my current project. Where the Closure is explicitly manipulated 
it certainly makes sense to keep that overload first-class.

What's the Apache process for doing this? I know how to open a ticket (heh), 
but can I just open a GitHub PR against apache/groovy? Looks like putting 
GROOVY-ABCD in the commit summary will auto-link it.

On Wed, Apr 28, 2021 at 11:19 AM Milles, Eric (TR Technology) 
<eric.mil...@thomsonreuters.com> wrote:
>
> For any DGM that accepts Closure but does not use closure delegation or 
> multiple closure param signatures, we could mark the Closure version 
> deprecated and add an @FunctionalInterface equivalent.  Existing code that 
> uses closure literals or method pointers should be okay.  There may be one or 
> two edge cases out there.
>
>
>
> For the ones that use delegation like "with" and "tap" I don't think there is 
> a strong case for making a change.
>
>
>
> I think it would probably be best to submit one JIRA ticket for each group of 
> methods.  That is, one for "collect", one for "findAll", etc.  So we can 
> break the problem down and test things a little at a time.
>
>
>
> From: Christopher Smith <chry...@gmail.com>
> Sent: Wednesday, April 28, 2021 11:02 AM
> To: dev@groovy.apache.org
> Subject: Re: GDK retrofit for Java functional interfaces
>
>
>
> The "side by side" approach is my second option; the only significant 
> downside is an increase in the surface area of the extension landscape. I 
> think Jochen excellently described the distinction of some cases (`with`) 
> where Closure awareness is still needed for reasons of delegate manipulation, 
> and in these cases adding a Function signature (essentially a "map" 
> operation) would make more sense.
>
>
>
> To be frank, I can't see a good reason for saying that `collect` (e.g.) 
> should just be given up in preference to an explicit stream. In such a case, 
> there is no disadvantage whatsoever that I can see to trimming the GDK 
> signature back to the more vanilla functional interface and interpreting a 
> Closure as that interface when desired, as is already done for interop 
> everywhere else.
>
>
>
> On Wed, Apr 28, 2021, 09:22 Milles, Eric (TR Technology) 
> <eric.mil...@thomsonreuters.com> wrote:
>
> Is there any reason that these cannot exist side-by-side as extension 
> methods?  If they are safe to co-exist, then you can create each of the 
> alternatives in turn within a sample project and try them out.  The extension 
> method mechanism is open and available.
>
>         public static <S,T> List<T> collect(Iterable<S> self,
> @ClosureParams(FirstParam.FirstGenericType.class) Closure<T>
> transform)
>
>         public static <S,T> List<T> collect(Iterable<S> self, 
> Function<? super S, ? extends T> transform)
>
>
>
> Otherwise, I think the going advice is to use Java streams if you want 
> a lambda/method reference friendly API.  There is an ticket in JIRA 
> about making streams a bit more "groovy":
> https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fissu
> es.apache.org%2Fjira%2Fbrowse%2FGROOVY-10026&amp;data=04%7C01%7Ceric.m
> illes%40thomsonreuters.com%7Cd2fd247908f84786338b08d90a63bc3c%7C62ccb8
> 646a1a4b5d8e1c397dec1a8258%7C0%7C0%7C637552245742549051%7CUnknown%7CTW
> FpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6
> Mn0%3D%7C1000&amp;sdata=TTaemEkQLuQ7uTXXMdA%2Fjgx2%2BJMxMg%2BnpBgqImKL
> fCI%3D&amp;reserved=0
>
>
> -----Original Message-----
> From: Christopher Smith <chrylis+gro...@gmail.com>
> Sent: Tuesday, April 27, 2021 6:37 PM
> To: dev@groovy.apache.org
> Subject: GDK retrofit for Java functional interfaces
>
> Since Paul is now threatening us with a 4.0 beta, I wanted to float an idea 
> that I've been thinking over for a bit now that might be best to add there 
> (though maybe it would be okay in 3 still, with the Java 8 baseline).
>
> A large number of the GDK extension methods (particularly stuff like 
> `with`, `collect`, and similar) have signatures that rely explicitly 
> on Closure for their strategies. This means that there are 
> interoperability problems with libraries that provide strategy 
> implementations as functional types; e.g., imagine this trivial
> example:
>
> ```
> public UnaryOperator<Integer> multiplier(int multiplicand) {
>   return x -> x * multiplicand;
> }
> ```
>
> I can't say `[1, 2, 3].collect(multiplier(2))`, because `collect` takes only 
> a Closure.
>
> I would like to (ideally) alter the signatures of the methods in 
> DefaultGroovyMethods and similar to replace Closure with the "more static" 
> interfaces where possible; most of these cases would end up being Function, 
> Consumer, and some of the other usual suspects, with some of the extension 
> methods being duplicated to account for the cases where the GDK currently 
> does runtime magic like arity detection.
> In the alternative, at least adding overrides for these would support 
> language-level interoperability.
>
> What is the opinion regarding making this change, and what kinds of 
> compatibility problems might result from replacing Closure with (e.g.) 
> Function rather than adding a new override?



--
Christopher Smith

Reply via email to