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 <dcwatso...@gmail.com> 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 <garydgreg...@gmail.com> > 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 <garydgreg...@gmail.com> > wrote: > > > > > Worth adding adding function(Function)? Seems low cost to add it > > > FailableFunction. > > > > > > Gary > > > > > > On Fri, Aug 4, 2023, 2:04 PM Rob Spoor <apa...@icemanx.nl> wrote: > > > > > >> With just one simple utility method you can get all the chaining you > > want: > > >> > > >> public static <T, R> Function<T, R> function(Function<T, R> > 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<MyBean, String> 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 > > >> > > >> > > >