Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-06 Thread Daniel Watson
Yep that's correct. You cant get strong typing with varargs. Overloading
(yes, lazy) is how I handle it right now. I believe there's really one 2
methods that do anything significant to accomplish the goal, one that calls
a single nested function, and one that calls a single nested BiConsumer.
The rest essentially just chain on top of those.

More thought could certainly be given to it. There may be other related use
cases I haven't encountered. And I've yet to need nesting beyond 3 levels,
but would  probaby offer methods that go a few levels beyond that, if only
because the cost is very little.

On Sun, Aug 6, 2023, 5:49 AM Rob Spoor  wrote:

> I don't think that function chaining with varargs works, except with
> UnaryOperator. After all, the output type of the first must be
> compatible with the input type of the second, the output type of the
> second must be compatible with the input type of the third, etc.
>
> If you want to continue this way, the best option would be to have some
> overloads:
>
>   Function nested(
>  Function first,
>  Function second)
>   Function nested(
>  Function first,
>  Function second,
>  R defaultValue)
>   Function nested(
>  Function first,
>  Function second,
>  Function third)
>   Function nested(
>  Function first,
>  Function second,
>  Function third,
>  R defaultValue)
>  ...
>
> If you're lazy you can delegate the overload with N functions to the
> overload with N-1 functions:
>
>   Function nested(
>  Function first,
>  Function second,
>  Function third,
>  Function fourth,
>  R defaultValue) {
>
>  return nested(first, nested(second, third, fourth),
>  defaultValue);
>  }
>
>
> Rob
>
>
> On 06/08/2023 01:28, Gary Gregory wrote:
> > I'm not sure the "nested" example API is quite what it should be, because
> > the last argument is the default value, you cannot make the input
> functions
> > a vararg, which seems very limiting. I should be able to use the same API
> > whether I need to go 1, 2, or N functions deep. I'm saying the above
> > independently of whether this type of code should be in Lang.
> >
> > Gary
> >
> > On Sat, Aug 5, 2023, 9:27 AM Daniel Watson  wrote:
> >
> >> Nice.
> >>
> >> Sounds like everyone is leaning towards "no". Would it be worth
> submitting
> >> a PR to include more usage examples - which I assume could also serve
> as a
> >> place to collect more feedback? Or just keep it within this thread given
> >> the way it's leaning? (or unless that consensus changes)
> >>
> >> Ultimately in my web/UI project the reduction (after using
> function(...))
> >> is something like...
> >>
> >> Failable.asFunction(Parent::getChild)
> >> .andThen(Optional::ofNullable)
> >> .andThen(o -> o.map(Child::getGrandChild))
> >> .andThen(o-> o.map(GrandChild::getName).orElse(defaultValue));
> >>
> >> vs my util method
> >>
> >> FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
> >> GrandChild::getName, defaultValue);
> >>
> >> So it's still a big difference in clarity for me, given how often its
> used.
> >> FWIW - My project is using Vaadin, and this util function is used to
> bind
> >> nested bean properties to Vaadin input fields. On that note - In
> addition
> >> to the bean "getter" binding, it also uses a similar util method to bind
> >> bean "setter" methods - because input fields obviously need access to
> both.
> >> The setter util call looks similar, with the last argument being
> >> a BiConsumer...
> >>
> >> FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
> >> GrandChild::setName);
> >>
> >> Although in general this code does not reference any Vaadin specific
> >> functionality, the overall use case may be quite specific to those
> needs,
> >> so all of these utilities may be better suited to a utils class within a
> >> vaadin specific library.
> >>
> >> Dan
> >>
> >> On Fri, Aug 4, 2023 at 9:11 PM Gary Gregory 
> >> wrote:
> >>
> >>> The function() method is a great technique, it's now in Functions and
> >>> FailableFunction (git master).
> >>>
> >>> I'll see later if it can be used within Lang. I know I can use it in
> >> other
> >>> projects.
> >>>
> >>> Wrt an API for a vararg of functions that implements chaining
> internally,
> >>> I'm not so sure. I've though I needed something like that in past, but
> >> I've
> >>> always ended up with other coding patterns I found better at the time
> for
> >>> whatever reason..
> >>>
> >>> Gary
> >>>
> >>> Gary
> >>>
> >>> On Fri, Aug 4, 2023, 3:24 PM Gary Gregory 
> >> wrote:
> >>>
>  Worth adding adding function(Function)? Seems low cost to add it
>  FailableFunction.
> 
>  Gary
> 
>  On Fri, Aug 4, 2023, 2:04 PM Rob Spoor  wrote:
> 
> > With just one simple utility method you can get all the 

Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-06 Thread Rob Spoor
I don't think that function chaining with varargs works, except with 
UnaryOperator. After all, the output type of the first must be 
compatible with the input type of the second, the output type of the 
second must be compatible with the input type of the third, etc.


If you want to continue this way, the best option would be to have some 
overloads:


 Function nested(
Function first,
Function second)
 Function nested(
Function first,
Function second,
R defaultValue)
 Function nested(
Function first,
Function second,
Function third)
 Function nested(
Function first,
Function second,
Function third,
R defaultValue)
...

If you're lazy you can delegate the overload with N functions to the 
overload with N-1 functions:


 Function nested(
Function first,
Function second,
Function third,
Function fourth,
R defaultValue) {

return nested(first, nested(second, third, fourth),
defaultValue);
}


Rob


On 06/08/2023 01:28, Gary Gregory wrote:

I'm not sure the "nested" example API is quite what it should be, because
the last argument is the default value, you cannot make the input functions
a vararg, which seems very limiting. I should be able to use the same API
whether I need to go 1, 2, or N functions deep. I'm saying the above
independently of whether this type of code should be in Lang.

Gary

On Sat, Aug 5, 2023, 9:27 AM Daniel Watson  wrote:


Nice.

Sounds like everyone is leaning towards "no". Would it be worth submitting
a PR to include more usage examples - which I assume could also serve as a
place to collect more feedback? Or just keep it within this thread given
the way it's leaning? (or unless that consensus changes)

Ultimately in my web/UI project the reduction (after using function(...))
is something like...

Failable.asFunction(Parent::getChild)
.andThen(Optional::ofNullable)
.andThen(o -> o.map(Child::getGrandChild))
.andThen(o-> o.map(GrandChild::getName).orElse(defaultValue));

vs my util method

FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
GrandChild::getName, defaultValue);

So it's still a big difference in clarity for me, given how often its used.
FWIW - My project is using Vaadin, and this util function is used to bind
nested bean properties to Vaadin input fields. On that note - In addition
to the bean "getter" binding, it also uses a similar util method to bind
bean "setter" methods - because input fields obviously need access to both.
The setter util call looks similar, with the last argument being
a BiConsumer...

FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
GrandChild::setName);

Although in general this code does not reference any Vaadin specific
functionality, the overall use case may be quite specific to those needs,
so all of these utilities may be better suited to a utils class within a
vaadin specific library.

Dan

On Fri, Aug 4, 2023 at 9:11 PM Gary Gregory 
wrote:


The function() method is a great technique, it's now in Functions and
FailableFunction (git master).

I'll see later if it can be used within Lang. I know I can use it in

other

projects.

Wrt an API for a vararg of functions that implements chaining internally,
I'm not so sure. I've though I needed something like that in past, but

I've

always ended up with other coding patterns I found better at the time for
whatever reason..

Gary

Gary

On Fri, Aug 4, 2023, 3:24 PM Gary Gregory 

wrote:



Worth adding adding function(Function)? Seems low cost to add it
FailableFunction.

Gary

On Fri, Aug 4, 2023, 2:04 PM Rob Spoor  wrote:


With just one simple utility method you can get all the chaining you

want:


  public static  Function function(Function

func) {

  return func;
  }

This doesn't look very useful, but it allows you to turn a method
reference or lambda into a typed Function without needing a cast.

After

that it's really simple using what's provided in the Java API:

  Function func = function(MyBean::getChild)
  .andThen(Child::getName);

You want a default value? Almost just as easy:

  someFrameworkThing.setProperty(function(ParentBean::getChild)
  .andThen(ChildBean::getName)
  .andThen(Optional::ofNullable)
  .andThen(o -> o.orElse("defaultName"));


On 04/08/2023 16:04, Daniel Watson wrote:

Asking for comments and thoughts on a potential new feature. Already
developed in a commons-like style, but dont want to submit PR

without

discussion as it may be considered out of scope or too use case

specific.


Justification and details...

I've run into a scenario a few times where nested lamba functions

would

be

incredibly useful. e.g.

MyBean::getChild::getName

Obviously this is not a language feature, but can be simulated in a


Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-05 Thread Gary Gregory
I'm not sure the "nested" example API is quite what it should be, because
the last argument is the default value, you cannot make the input functions
a vararg, which seems very limiting. I should be able to use the same API
whether I need to go 1, 2, or N functions deep. I'm saying the above
independently of whether this type of code should be in Lang.

Gary

On Sat, Aug 5, 2023, 9:27 AM Daniel Watson  wrote:

> Nice.
>
> Sounds like everyone is leaning towards "no". Would it be worth submitting
> a PR to include more usage examples - which I assume could also serve as a
> place to collect more feedback? Or just keep it within this thread given
> the way it's leaning? (or unless that consensus changes)
>
> Ultimately in my web/UI project the reduction (after using function(...))
> is something like...
>
> Failable.asFunction(Parent::getChild)
> .andThen(Optional::ofNullable)
> .andThen(o -> o.map(Child::getGrandChild))
> .andThen(o-> o.map(GrandChild::getName).orElse(defaultValue));
>
> vs my util method
>
> FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
> GrandChild::getName, defaultValue);
>
> So it's still a big difference in clarity for me, given how often its used.
> FWIW - My project is using Vaadin, and this util function is used to bind
> nested bean properties to Vaadin input fields. On that note - In addition
> to the bean "getter" binding, it also uses a similar util method to bind
> bean "setter" methods - because input fields obviously need access to both.
> The setter util call looks similar, with the last argument being
> a BiConsumer...
>
> FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
> GrandChild::setName);
>
> Although in general this code does not reference any Vaadin specific
> functionality, the overall use case may be quite specific to those needs,
> so all of these utilities may be better suited to a utils class within a
> vaadin specific library.
>
> Dan
>
> On Fri, Aug 4, 2023 at 9:11 PM Gary Gregory 
> wrote:
>
> > The function() method is a great technique, it's now in Functions and
> > FailableFunction (git master).
> >
> > I'll see later if it can be used within Lang. I know I can use it in
> other
> > projects.
> >
> > Wrt an API for a vararg of functions that implements chaining internally,
> > I'm not so sure. I've though I needed something like that in past, but
> I've
> > always ended up with other coding patterns I found better at the time for
> > whatever reason..
> >
> > Gary
> >
> > Gary
> >
> > On Fri, Aug 4, 2023, 3:24 PM Gary Gregory 
> wrote:
> >
> > > Worth adding adding function(Function)? Seems low cost to add it
> > > FailableFunction.
> > >
> > > Gary
> > >
> > > On Fri, Aug 4, 2023, 2:04 PM Rob Spoor  wrote:
> > >
> > >> With just one simple utility method you can get all the chaining you
> > want:
> > >>
> > >>  public static  Function function(Function
> func) {
> > >>  return func;
> > >>  }
> > >>
> > >> This doesn't look very useful, but it allows you to turn a method
> > >> reference or lambda into a typed Function without needing a cast.
> After
> > >> that it's really simple using what's provided in the Java API:
> > >>
> > >>  Function func = function(MyBean::getChild)
> > >>  .andThen(Child::getName);
> > >>
> > >> You want a default value? Almost just as easy:
> > >>
> > >>  someFrameworkThing.setProperty(function(ParentBean::getChild)
> > >>  .andThen(ChildBean::getName)
> > >>  .andThen(Optional::ofNullable)
> > >>  .andThen(o -> o.orElse("defaultName"));
> > >>
> > >>
> > >> On 04/08/2023 16:04, Daniel Watson wrote:
> > >> > Asking for comments and thoughts on a potential new feature. Already
> > >> > developed in a commons-like style, but dont want to submit PR
> without
> > >> > discussion as it may be considered out of scope or too use case
> > >> specific.
> > >> >
> > >> > Justification and details...
> > >> >
> > >> > I've run into a scenario a few times where nested lamba functions
> > would
> > >> be
> > >> > incredibly useful. e.g.
> > >> >
> > >> > MyBean::getChild::getName
> > >> >
> > >> > Obviously this is not a language feature, but can be simulated in a
> > >> useful
> > >> > way. So far my use has mostly been related to code that works with
> > POJO
> > >> > beans, and frameworks that use function references to understand
> those
> > >> > beans and properties. Specifically useful where the context of the
> > code
> > >> > block is the parent entity, but you need to reference a child, and
> > >> without
> > >> > nested lambdas you end up with things like the below...
> > >> >
> > >> > ParentBean parentBean = new ParentBean();
> > >> > parentBean.setChild(new ChildBean("name"));
> > >> > //imagine that FrameworkThing is a generic class, and thus the
> generic
> > >> type
> > >> > is ParentBean
> > >> > FrameworkThing someFrameworkThing = new FrameworkThing
> > >> (ParentBean.class)
> > >> > //but we need to get to a property of a 

Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-05 Thread Daniel Watson
Nice.

Sounds like everyone is leaning towards "no". Would it be worth submitting
a PR to include more usage examples - which I assume could also serve as a
place to collect more feedback? Or just keep it within this thread given
the way it's leaning? (or unless that consensus changes)

Ultimately in my web/UI project the reduction (after using function(...))
is something like...

Failable.asFunction(Parent::getChild)
.andThen(Optional::ofNullable)
.andThen(o -> o.map(Child::getGrandChild))
.andThen(o-> o.map(GrandChild::getName).orElse(defaultValue));

vs my util method

FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
GrandChild::getName, defaultValue);

So it's still a big difference in clarity for me, given how often its used.
FWIW - My project is using Vaadin, and this util function is used to bind
nested bean properties to Vaadin input fields. On that note - In addition
to the bean "getter" binding, it also uses a similar util method to bind
bean "setter" methods - because input fields obviously need access to both.
The setter util call looks similar, with the last argument being
a BiConsumer...

FunctionUtils.nested(Parent::getChild, Child::getGrandChild,
GrandChild::setName);

Although in general this code does not reference any Vaadin specific
functionality, the overall use case may be quite specific to those needs,
so all of these utilities may be better suited to a utils class within a
vaadin specific library.

Dan

On Fri, Aug 4, 2023 at 9:11 PM Gary Gregory  wrote:

> The function() method is a great technique, it's now in Functions and
> FailableFunction (git master).
>
> I'll see later if it can be used within Lang. I know I can use it in other
> projects.
>
> Wrt an API for a vararg of functions that implements chaining internally,
> I'm not so sure. I've though I needed something like that in past, but I've
> always ended up with other coding patterns I found better at the time for
> whatever reason..
>
> Gary
>
> Gary
>
> On Fri, Aug 4, 2023, 3:24 PM Gary Gregory  wrote:
>
> > Worth adding adding function(Function)? Seems low cost to add it
> > FailableFunction.
> >
> > Gary
> >
> > On Fri, Aug 4, 2023, 2:04 PM Rob Spoor  wrote:
> >
> >> With just one simple utility method you can get all the chaining you
> want:
> >>
> >>  public static  Function function(Function func) {
> >>  return func;
> >>  }
> >>
> >> This doesn't look very useful, but it allows you to turn a method
> >> reference or lambda into a typed Function without needing a cast. After
> >> that it's really simple using what's provided in the Java API:
> >>
> >>  Function func = function(MyBean::getChild)
> >>  .andThen(Child::getName);
> >>
> >> You want a default value? Almost just as easy:
> >>
> >>  someFrameworkThing.setProperty(function(ParentBean::getChild)
> >>  .andThen(ChildBean::getName)
> >>  .andThen(Optional::ofNullable)
> >>  .andThen(o -> o.orElse("defaultName"));
> >>
> >>
> >> On 04/08/2023 16:04, Daniel Watson wrote:
> >> > Asking for comments and thoughts on a potential new feature. Already
> >> > developed in a commons-like style, but dont want to submit PR without
> >> > discussion as it may be considered out of scope or too use case
> >> specific.
> >> >
> >> > Justification and details...
> >> >
> >> > I've run into a scenario a few times where nested lamba functions
> would
> >> be
> >> > incredibly useful. e.g.
> >> >
> >> > MyBean::getChild::getName
> >> >
> >> > Obviously this is not a language feature, but can be simulated in a
> >> useful
> >> > way. So far my use has mostly been related to code that works with
> POJO
> >> > beans, and frameworks that use function references to understand those
> >> > beans and properties. Specifically useful where the context of the
> code
> >> > block is the parent entity, but you need to reference a child, and
> >> without
> >> > nested lambdas you end up with things like the below...
> >> >
> >> > ParentBean parentBean = new ParentBean();
> >> > parentBean.setChild(new ChildBean("name"));
> >> > //imagine that FrameworkThing is a generic class, and thus the generic
> >> type
> >> > is ParentBean
> >> > FrameworkThing someFrameworkThing = new FrameworkThing
> >> (ParentBean.class)
> >> > //but we need to get to a property of a child bean
> >> > someFrameworkThing.setProperty((parentBean) ->  {
> >> >
> >> > return parentBean.getChild().getName();
> >> >
> >> > });
> >> >
> >> > Obviously this could be handled with a getChildName() method on the
> >> parent
> >> > bean, but that has pitfalls as well (e.g. bean class cannot be
> changed,
> >> or
> >> > adding of properties interferes with other usage of the class e.g.
> JPA,
> >> > JAX).  However with a util class the second call can be reduced to
> >> > something like below, leaving the bean API untouched.
> >> >
> >> >
> >>
> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName));
> >> >

Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-04 Thread Gary Gregory
The function() method is a great technique, it's now in Functions and
FailableFunction (git master).

I'll see later if it can be used within Lang. I know I can use it in other
projects.

Wrt an API for a vararg of functions that implements chaining internally,
I'm not so sure. I've though I needed something like that in past, but I've
always ended up with other coding patterns I found better at the time for
whatever reason..

Gary

Gary

On Fri, Aug 4, 2023, 3:24 PM Gary Gregory  wrote:

> Worth adding adding function(Function)? Seems low cost to add it
> FailableFunction.
>
> Gary
>
> On Fri, Aug 4, 2023, 2:04 PM Rob Spoor  wrote:
>
>> With just one simple utility method you can get all the chaining you want:
>>
>>  public static  Function function(Function func) {
>>  return func;
>>  }
>>
>> This doesn't look very useful, but it allows you to turn a method
>> reference or lambda into a typed Function without needing a cast. After
>> that it's really simple using what's provided in the Java API:
>>
>>  Function func = function(MyBean::getChild)
>>  .andThen(Child::getName);
>>
>> You want a default value? Almost just as easy:
>>
>>  someFrameworkThing.setProperty(function(ParentBean::getChild)
>>  .andThen(ChildBean::getName)
>>  .andThen(Optional::ofNullable)
>>  .andThen(o -> o.orElse("defaultName"));
>>
>>
>> On 04/08/2023 16:04, Daniel Watson wrote:
>> > Asking for comments and thoughts on a potential new feature. Already
>> > developed in a commons-like style, but dont want to submit PR without
>> > discussion as it may be considered out of scope or too use case
>> specific.
>> >
>> > Justification and details...
>> >
>> > I've run into a scenario a few times where nested lamba functions would
>> be
>> > incredibly useful. e.g.
>> >
>> > MyBean::getChild::getName
>> >
>> > Obviously this is not a language feature, but can be simulated in a
>> useful
>> > way. So far my use has mostly been related to code that works with POJO
>> > beans, and frameworks that use function references to understand those
>> > beans and properties. Specifically useful where the context of the code
>> > block is the parent entity, but you need to reference a child, and
>> without
>> > nested lambdas you end up with things like the below...
>> >
>> > ParentBean parentBean = new ParentBean();
>> > parentBean.setChild(new ChildBean("name"));
>> > //imagine that FrameworkThing is a generic class, and thus the generic
>> type
>> > is ParentBean
>> > FrameworkThing someFrameworkThing = new FrameworkThing
>> (ParentBean.class)
>> > //but we need to get to a property of a child bean
>> > someFrameworkThing.setProperty((parentBean) ->  {
>> >
>> > return parentBean.getChild().getName();
>> >
>> > });
>> >
>> > Obviously this could be handled with a getChildName() method on the
>> parent
>> > bean, but that has pitfalls as well (e.g. bean class cannot be changed,
>> or
>> > adding of properties interferes with other usage of the class e.g. JPA,
>> > JAX).  However with a util class the second call can be reduced to
>> > something like below, leaving the bean API untouched.
>> >
>> >
>> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName));
>> >
>> > Taken alone, that single reduction may seem trivial, but in a scenario
>> > where these nested references are commonly needed, the reduction makes
>> the
>> > code clearer (In my opinion), as it is immediately apparent on a single
>> > line of code that the reference is a simple nested property, rather than
>> > having to interpret an inline lambda function. It also discourages
>> errant
>> > placement of code by avoiding the inline function (since the only
>> purpose
>> > of the lambda was to retrieve a single nested value). In addition, If
>> > intermediate nulls need to be handled then the reduction becomes more
>> > apparent, as the null checks can be handled in the util class rather
>> than
>> > cluttering the app code. e.g.
>> >
>> >
>> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,"defaultName"));
>> > //or...
>> >
>> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,null));
>> >
>> > The third parameter here is a String (typed genetically based on the
>> return
>> > type of getName) and indicates the default value to be returned if the
>> > first call to getChild() returns null. e.g. it replaces something
>> like...
>> >
>> > someFrameworkThing.setProperty((parentBean) ->  {
>> >
>> > ChildBean cb = parentBean.getChild();
>> > if(cb == null) return null; //or other default value
>> > else return cb.getName();
>> >
>> > });
>> >
>> > Given that commons-lang aims to extend existing language features, this
>> > seemed like a reasonable place for a nested lambda util class. So far my
>> > concerns are...
>> >
>> > 1. Does this feel too specific to an application to warrant
>> 

Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-04 Thread Gary Gregory
Worth adding adding function(Function)? Seems low cost to add it
FailableFunction.

Gary

On Fri, Aug 4, 2023, 2:04 PM Rob Spoor  wrote:

> With just one simple utility method you can get all the chaining you want:
>
>  public static  Function function(Function func) {
>  return func;
>  }
>
> This doesn't look very useful, but it allows you to turn a method
> reference or lambda into a typed Function without needing a cast. After
> that it's really simple using what's provided in the Java API:
>
>  Function func = function(MyBean::getChild)
>  .andThen(Child::getName);
>
> You want a default value? Almost just as easy:
>
>  someFrameworkThing.setProperty(function(ParentBean::getChild)
>  .andThen(ChildBean::getName)
>  .andThen(Optional::ofNullable)
>  .andThen(o -> o.orElse("defaultName"));
>
>
> On 04/08/2023 16:04, Daniel Watson wrote:
> > Asking for comments and thoughts on a potential new feature. Already
> > developed in a commons-like style, but dont want to submit PR without
> > discussion as it may be considered out of scope or too use case specific.
> >
> > Justification and details...
> >
> > I've run into a scenario a few times where nested lamba functions would
> be
> > incredibly useful. e.g.
> >
> > MyBean::getChild::getName
> >
> > Obviously this is not a language feature, but can be simulated in a
> useful
> > way. So far my use has mostly been related to code that works with POJO
> > beans, and frameworks that use function references to understand those
> > beans and properties. Specifically useful where the context of the code
> > block is the parent entity, but you need to reference a child, and
> without
> > nested lambdas you end up with things like the below...
> >
> > ParentBean parentBean = new ParentBean();
> > parentBean.setChild(new ChildBean("name"));
> > //imagine that FrameworkThing is a generic class, and thus the generic
> type
> > is ParentBean
> > FrameworkThing someFrameworkThing = new FrameworkThing (ParentBean.class)
> > //but we need to get to a property of a child bean
> > someFrameworkThing.setProperty((parentBean) ->  {
> >
> > return parentBean.getChild().getName();
> >
> > });
> >
> > Obviously this could be handled with a getChildName() method on the
> parent
> > bean, but that has pitfalls as well (e.g. bean class cannot be changed,
> or
> > adding of properties interferes with other usage of the class e.g. JPA,
> > JAX).  However with a util class the second call can be reduced to
> > something like below, leaving the bean API untouched.
> >
> >
> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName));
> >
> > Taken alone, that single reduction may seem trivial, but in a scenario
> > where these nested references are commonly needed, the reduction makes
> the
> > code clearer (In my opinion), as it is immediately apparent on a single
> > line of code that the reference is a simple nested property, rather than
> > having to interpret an inline lambda function. It also discourages errant
> > placement of code by avoiding the inline function (since the only purpose
> > of the lambda was to retrieve a single nested value). In addition, If
> > intermediate nulls need to be handled then the reduction becomes more
> > apparent, as the null checks can be handled in the util class rather than
> > cluttering the app code. e.g.
> >
> >
> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,"defaultName"));
> > //or...
> >
> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,null));
> >
> > The third parameter here is a String (typed genetically based on the
> return
> > type of getName) and indicates the default value to be returned if the
> > first call to getChild() returns null. e.g. it replaces something like...
> >
> > someFrameworkThing.setProperty((parentBean) ->  {
> >
> > ChildBean cb = parentBean.getChild();
> > if(cb == null) return null; //or other default value
> > else return cb.getName();
> >
> > });
> >
> > Given that commons-lang aims to extend existing language features, this
> > seemed like a reasonable place for a nested lambda util class. So far my
> > concerns are...
> >
> > 1. Does this feel too specific to an application to warrant
> inclusion in
> > commons? (For me it has been useful enough to place into a common
> library,
> > but commons-lang has a broader scope)
> > 2. If not commons-lang, is there some other commons library that
> this is
> > more suited to?
> > 3. There are still wrinkles that may prove complex and potentially
> > overly specific e.g. exception handling. Does that potential
> complexity
> > make it not worth adding?
> > 4. Assuming the features discussed here *are* valuable, Is handling
> only
> > java.util.Function a complete-enough feature? Or is it useless
> unless it
> > also attempts to 

Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-04 Thread Daniel Watson
Appreciate the feedback. That's a great point. I missed the potential of
the andThen(...) method.

One minor thing to point out - My proposed purpose of the default value
parameter was not to substitute the final value if it is null, but to
substitute the final value if it cannot be obtained, due the *parent* being
null. So in my example, it is the return value of getChild() that would be
null, and your code would fail with a NPE. To handle this using the
chaining approach I think would look something like:

function(ParentBean::getChild)

.andThen(Optional::ofNullable)
.andThen(o -> {

return o.map(ChildBean::getName).orElse("defaultName");

});

So overall it's similar to yours, you just need the .map() call to change
the optional type to match the final return type.

That probably covers a lot of scenarios, however I still consider it a bit
tedious, and it becomes even more tedious if we nest it one level further
because the handling of null is now always an inline function. (I realize
that level of nesting might be rare. I personally have needed it, but I
understand that alone is not justification enough)

For my usage of it, It's still much clearer to see a util method call, with
method references, rather than chaining via andThen, because most uses need
to handle null, which means I'd still be stuck with inline functions
everywhere. In the end the biggest benefit of the util call is the clarity
of quickly knowing that the purpose is to retrieve a simple nested
property, which I don't think you can realistically get when having to
decipher a chain of functions and optionals.

Dan


On Fri, Aug 4, 2023 at 2:04 PM Rob Spoor  wrote:

> With just one simple utility method you can get all the chaining you want:
>
>  public static  Function function(Function func) {
>  return func;
>  }
>
> This doesn't look very useful, but it allows you to turn a method
> reference or lambda into a typed Function without needing a cast. After
> that it's really simple using what's provided in the Java API:
>
>  Function func = function(MyBean::getChild)
>  .andThen(Child::getName);
>
> You want a default value? Almost just as easy:
>
>  someFrameworkThing.setProperty(function(ParentBean::getChild)
>  .andThen(ChildBean::getName)
>  .andThen(Optional::ofNullable)
>  .andThen(o -> o.orElse("defaultName"));
>
>
> On 04/08/2023 16:04, Daniel Watson wrote:
> > Asking for comments and thoughts on a potential new feature. Already
> > developed in a commons-like style, but dont want to submit PR without
> > discussion as it may be considered out of scope or too use case specific.
> >
> > Justification and details...
> >
> > I've run into a scenario a few times where nested lamba functions would
> be
> > incredibly useful. e.g.
> >
> > MyBean::getChild::getName
> >
> > Obviously this is not a language feature, but can be simulated in a
> useful
> > way. So far my use has mostly been related to code that works with POJO
> > beans, and frameworks that use function references to understand those
> > beans and properties. Specifically useful where the context of the code
> > block is the parent entity, but you need to reference a child, and
> without
> > nested lambdas you end up with things like the below...
> >
> > ParentBean parentBean = new ParentBean();
> > parentBean.setChild(new ChildBean("name"));
> > //imagine that FrameworkThing is a generic class, and thus the generic
> type
> > is ParentBean
> > FrameworkThing someFrameworkThing = new FrameworkThing (ParentBean.class)
> > //but we need to get to a property of a child bean
> > someFrameworkThing.setProperty((parentBean) ->  {
> >
> > return parentBean.getChild().getName();
> >
> > });
> >
> > Obviously this could be handled with a getChildName() method on the
> parent
> > bean, but that has pitfalls as well (e.g. bean class cannot be changed,
> or
> > adding of properties interferes with other usage of the class e.g. JPA,
> > JAX).  However with a util class the second call can be reduced to
> > something like below, leaving the bean API untouched.
> >
> >
> someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName));
> >
> > Taken alone, that single reduction may seem trivial, but in a scenario
> > where these nested references are commonly needed, the reduction makes
> the
> > code clearer (In my opinion), as it is immediately apparent on a single
> > line of code that the reference is a simple nested property, rather than
> > having to interpret an inline lambda function. It also discourages errant
> > placement of code by avoiding the inline function (since the only purpose
> > of the lambda was to retrieve a single nested value). In addition, If
> > intermediate nulls need to be handled then the reduction becomes more
> > apparent, as the null checks can be handled in the util class rather than
> > cluttering the app code. e.g.
> >
> >
> 

Re: [commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-04 Thread Rob Spoor

With just one simple utility method you can get all the chaining you want:

public static  Function function(Function func) {
return func;
}

This doesn't look very useful, but it allows you to turn a method 
reference or lambda into a typed Function without needing a cast. After 
that it's really simple using what's provided in the Java API:


Function func = function(MyBean::getChild)
.andThen(Child::getName);

You want a default value? Almost just as easy:

someFrameworkThing.setProperty(function(ParentBean::getChild)
.andThen(ChildBean::getName)
.andThen(Optional::ofNullable)
.andThen(o -> o.orElse("defaultName"));


On 04/08/2023 16:04, Daniel Watson wrote:

Asking for comments and thoughts on a potential new feature. Already
developed in a commons-like style, but dont want to submit PR without
discussion as it may be considered out of scope or too use case specific.

Justification and details...

I've run into a scenario a few times where nested lamba functions would be
incredibly useful. e.g.

MyBean::getChild::getName

Obviously this is not a language feature, but can be simulated in a useful
way. So far my use has mostly been related to code that works with POJO
beans, and frameworks that use function references to understand those
beans and properties. Specifically useful where the context of the code
block is the parent entity, but you need to reference a child, and without
nested lambdas you end up with things like the below...

ParentBean parentBean = new ParentBean();
parentBean.setChild(new ChildBean("name"));
//imagine that FrameworkThing is a generic class, and thus the generic type
is ParentBean
FrameworkThing someFrameworkThing = new FrameworkThing (ParentBean.class)
//but we need to get to a property of a child bean
someFrameworkThing.setProperty((parentBean) ->  {

return parentBean.getChild().getName();

});

Obviously this could be handled with a getChildName() method on the parent
bean, but that has pitfalls as well (e.g. bean class cannot be changed, or
adding of properties interferes with other usage of the class e.g. JPA,
JAX).  However with a util class the second call can be reduced to
something like below, leaving the bean API untouched.

someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName));

Taken alone, that single reduction may seem trivial, but in a scenario
where these nested references are commonly needed, the reduction makes the
code clearer (In my opinion), as it is immediately apparent on a single
line of code that the reference is a simple nested property, rather than
having to interpret an inline lambda function. It also discourages errant
placement of code by avoiding the inline function (since the only purpose
of the lambda was to retrieve a single nested value). In addition, If
intermediate nulls need to be handled then the reduction becomes more
apparent, as the null checks can be handled in the util class rather than
cluttering the app code. e.g.

someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,"defaultName"));
//or...
someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,null));

The third parameter here is a String (typed genetically based on the return
type of getName) and indicates the default value to be returned if the
first call to getChild() returns null. e.g. it replaces something like...

someFrameworkThing.setProperty((parentBean) ->  {

ChildBean cb = parentBean.getChild();
if(cb == null) return null; //or other default value
else return cb.getName();

});

Given that commons-lang aims to extend existing language features, this
seemed like a reasonable place for a nested lambda util class. So far my
concerns are...

1. Does this feel too specific to an application to warrant inclusion in
commons? (For me it has been useful enough to place into a common library,
but commons-lang has a broader scope)
2. If not commons-lang, is there some other commons library that this is
more suited to?
3. There are still wrinkles that may prove complex and potentially
overly specific e.g. exception handling. Does that potential complexity
make it not worth adding?
4. Assuming the features discussed here *are* valuable, Is handling only
java.util.Function a complete-enough feature? Or is it useless unless it
also attempts to handle BiFunctions - which become increasingly complex
(potentially unfeasible) to implement - i.e. is it too big a feature to
consider including?

If folks feel like this is a solid "no" let me know. If the devil is in the
details and we need to see the PR first I can do that as well.

Dan




-
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org



[commons-lang] Comments on new FunctionUtils / nested lambda feature

2023-08-04 Thread Daniel Watson
Asking for comments and thoughts on a potential new feature. Already
developed in a commons-like style, but dont want to submit PR without
discussion as it may be considered out of scope or too use case specific.

Justification and details...

I've run into a scenario a few times where nested lamba functions would be
incredibly useful. e.g.

MyBean::getChild::getName

Obviously this is not a language feature, but can be simulated in a useful
way. So far my use has mostly been related to code that works with POJO
beans, and frameworks that use function references to understand those
beans and properties. Specifically useful where the context of the code
block is the parent entity, but you need to reference a child, and without
nested lambdas you end up with things like the below...

ParentBean parentBean = new ParentBean();
parentBean.setChild(new ChildBean("name"));
//imagine that FrameworkThing is a generic class, and thus the generic type
is ParentBean
FrameworkThing someFrameworkThing = new FrameworkThing (ParentBean.class)
//but we need to get to a property of a child bean
someFrameworkThing.setProperty((parentBean) ->  {

return parentBean.getChild().getName();

});

Obviously this could be handled with a getChildName() method on the parent
bean, but that has pitfalls as well (e.g. bean class cannot be changed, or
adding of properties interferes with other usage of the class e.g. JPA,
JAX).  However with a util class the second call can be reduced to
something like below, leaving the bean API untouched.

someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName));

Taken alone, that single reduction may seem trivial, but in a scenario
where these nested references are commonly needed, the reduction makes the
code clearer (In my opinion), as it is immediately apparent on a single
line of code that the reference is a simple nested property, rather than
having to interpret an inline lambda function. It also discourages errant
placement of code by avoiding the inline function (since the only purpose
of the lambda was to retrieve a single nested value). In addition, If
intermediate nulls need to be handled then the reduction becomes more
apparent, as the null checks can be handled in the util class rather than
cluttering the app code. e.g.

someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,"defaultName"));
//or...
someFrameworkThing.setProperty(FunctionUtils.nested(ParentBean::getChild,ChildBean::getName,null));

The third parameter here is a String (typed genetically based on the return
type of getName) and indicates the default value to be returned if the
first call to getChild() returns null. e.g. it replaces something like...

someFrameworkThing.setProperty((parentBean) ->  {

ChildBean cb = parentBean.getChild();
if(cb == null) return null; //or other default value
else return cb.getName();

});

Given that commons-lang aims to extend existing language features, this
seemed like a reasonable place for a nested lambda util class. So far my
concerns are...

   1. Does this feel too specific to an application to warrant inclusion in
   commons? (For me it has been useful enough to place into a common library,
   but commons-lang has a broader scope)
   2. If not commons-lang, is there some other commons library that this is
   more suited to?
   3. There are still wrinkles that may prove complex and potentially
   overly specific e.g. exception handling. Does that potential complexity
   make it not worth adding?
   4. Assuming the features discussed here *are* valuable, Is handling only
   java.util.Function a complete-enough feature? Or is it useless unless it
   also attempts to handle BiFunctions - which become increasingly complex
   (potentially unfeasible) to implement - i.e. is it too big a feature to
   consider including?

If folks feel like this is a solid "no" let me know. If the devil is in the
details and we need to see the PR first I can do that as well.

Dan