Hi, On Sun, Apr 24, 2016 at 8:56 PM, Tobias Soloschenko < [email protected]> wrote:
> Hi, > > I am able to write some docs if the integration is finished. > What do you think about releasing 8.0.0-M1 soon ? Sven just merged the request handler execution improvements. As soon as the IRequestListener improvements are merged to master I think we are ready for M1. Hopefully this will lead to some feedback on the new stuff! > > kind regards > > Tobias > > > Am 24.04.2016 um 20:51 schrieb Sven Meier <[email protected]>: > > > > Hi Martin, > > > > that's quite nice to have these methods in IModel actually. > > > > Java 8 default methods to the rescue :) > > > > Regards > > Sven > > > > > > > >> On 24.04.2016 17:20, Martin Grigorov wrote: > >> Hi, > >> > >> I've moved Matthias' code to IModel in branch monad-model ( > >> > https://git1-us-west.apache.org/repos/asf?p=wicket.git;a=commitdiff;h=484132a8;hp=f2f0ba067e9cf3a4f31eb3c387d6244c3c06c44b > >> ) > >> Just to see how it will look like. > >> And I think it is not bad at all! > >> By moving these methods to IModel we make them available to all impls. > Once > >> such method is called it effectively makes the model read-only, because > a > >> new IModel is returned and IModel#setObject() already throws an > exception. > >> If the application developer wants a read-write model then (s)he has to > use > >> #flatMap() and return a writeable model. > >> > >> The branch is just a playground! > >> I've touched one of the existing tests just because I was lazy to > create a > >> new one. > >> > >> > >> Martin Grigorov > >> Wicket Training and Consulting > >> https://twitter.com/mtgrigorov > >> > >> On Sun, Apr 24, 2016 at 12:56 PM, Matthias Metzger < > >> [email protected]> wrote: > >> > >>> Hi, > >>> > >>> > >>> thanks for your comments! > >>> > >>> > >>>>> whether those transformations should be done by a Model or > >>>>> it would be better to be done by Functions and finally a Model > >>>>> would consume the result > >>>> my thoughts exactly: Chaining of functions is a broader topic. Note > how > >>>> ReadOnlyModel and LambdaColumn have identical #map() functions. > >>> > >>>> Furthermore Java Function objects already support chaining with > >>> #andThen(). > >>>> The Java compiler just doesn't allow calling methods on a method > >>> reference: > >>> > >>>> // doesn't work > >>>> IModel<String> streetModel = LambdaModel.of(target, > >>>> Person::getAdress.andThen(Address::getStreet)); > >>> I agree with both of you. The 'first' method is actually something > Java 8 > >>> is totally missing in my opinion, which is one reason for my ideas. The > >>> other one being potential null values in the above, which we could > rule out > >>> using Optional: > >>> > >>> LambdaModel.of(target, p -> > >>> > Optional.ofNullable(p).map(Person::getAddress).map(Address::getStreet).orElse("n/a")); > >>> > >>> Maybe this is a better way to deal with this sort of chaining, because > >>> it's actually the same approach for the 'LambdaColumn' and uses > >>> mechanisms, which are more general. I think one could even make an > argument > >>> to create a getter for this case. The 'apply' could then be done in the > >>> following way: > >>> > >>> LambdaModel.of(target, p -> Optional.ofNullable(p). > >>> map(Person::getName). > >>> map(name -> house.getObject().apply(name)). > >>> orElse("n/a")); > >>> > >>> > >>>> - if this functionality should be in a model then in which class? > >>>> -- AbstractReadOnlyModel is deprecated. Maybe we should un-deprecate > it > >>> ?! > >>>> -- the name "ReadOnlyModel" doesn't tell me what nice functionality I > >>>> could expect from it. But on the side all these methods should be > >>> provided > >>>> only by a read-only model. Or not? I see they can easily be put in > IModel > >>>> class, but then the developer should be careful with the usage of > >>>> #setObject() > >>> > >>> Despite the above, I'll still answer this concern: > >>> You are right. The naming is absolutely terrible and I have been > >>> struggling with a good name not involving all the Haskell stuff I have > been > >>> taking inspiration from. At the moment I would tend to call it > >>> MappableModel<T>. In light of the 8.x changes, I would let it implement > >>> IModel<T> - so no need for un-deprecating AbstractReadOnlyModel<T>. > This > >>> was just because I have been playing around with 7.x. Yes, > ReadOnlyModel > >>> and/or LoadableDetachableModel and also maybe a MappableColumn. > Basically > >>> everything which mostly reads. > >>> > >>> I have been tinkering with a method '#toIModel(BiConsumer<T, U> > setter)', > >>> transforming the MappableModel to an IModel. That comes with some > >>> non-obvious caveats however. > >>> > >>> Have a nice rest of the day, > >>> > >>> Matthias > >>> > >>> > >>> > >>> > >>> ----- Ursprüngliche Message ----- > >>> Von: Sven Meier <[email protected]> > >>> An: [email protected] > >>> Gesendet: 12:23 Sonntag, 24.April 2016 > >>> Betreff: Re: Further Lambda Model ideas > >>> > >>> Hi, > >>> > >>>> whether those transformations should be done by a Model or > >>>> it would be better to be done by Functions and finally a Model > >>>> would consume the result > >>> my thoughts exactly: Chaining of functions is a broader topic. Note how > >>> ReadOnlyModel and LambdaColumn have identical #map() functions. > >>> > >>> Furthermore Java Function objects already support chaining with > #andThen(). > >>> The Java compiler just doesn't allow calling methods on a method > reference: > >>> > >>> // doesn't work > >>> IModel<String> streetModel = LambdaModel.of(target, > >>> Person::getAdress.andThen(Address::getStreet)); > >>> > >>> You have to use a method call to get an actual function object first: > >>> > >>> // this does work > >>> IModel<String> streetModel = LambdaModel.of(target, > >>> first(Person::getAdress).andThen(Address::getStreet)); > >>> > >>> private <T1, T2> WicketFunction<T1, T2> first(WicketFunction<T1, > >>> T2> func) { > >>> return func; > >>> } > >>> > >>> For this to work we have to add an additional method for serialization > >>> into WicketFunction though: > >>> > >>> // specialization of the super method for serializable functions > >>> default <V> WicketFunction<T, V> andThen(WicketFunction<? super R, > >>> ? extends V> after) > >>> { > >>> Objects.requireNonNull(after); > >>> return (T t) -> after.apply(apply(t)); > >>> } > >>> > >>> Have fun > >>> Sven > >>> > >>> > >>>> On 24.04.2016 11:34, Martin Grigorov wrote: > >>>> On Sun, Apr 24, 2016 at 11:16 AM, Martin Grigorov < > [email protected]> > >>>> wrote: > >>>> > >>>>> Hi, > >>>>> > >>>>> I like the functionality provided by ReadOnlyModel! > >>>>> I have two questions/doubts: > >>>>> - whether those transformations should be done by a Model or it > would be > >>>>> better to be done by Functions and finally a Model would consume the > >>> result > >>>>> - if this functionality should be in a model then in which class? > >>>>> -- AbstractReadOnlyModel is deprecated. Maybe we should un-deprecate > it > >>> ?! > >>>>> -- the name "ReadOnlyModel" doesn't tell me what nice functionality I > >>>>> could expect from it. But on the side all these methods should be > >>> provided > >>>>> only by a read-only model. Or not? I see they can easily be put in > >>> IModel > >>>>> class, but then the developer should be careful with the usage of > >>>>> #setObject() > >>>>> > >>>>> I think a better solution would be a read-write Model that uses > >>>>> composition of functions internally for all the transformations. > >>>>> #setObject() will manipulate the model's object. #getObject() will > apply > >>>>> the model object to the composed function to get the final result. > >>>> This won't work. The mapping cannot be in the same IModel, a new > IModel > >>>> should be returned. > >>>> > >>>> > >>>>> Martin Grigorov > >>>>> Wicket Training and Consulting > >>>>> https://twitter.com/mtgrigorov > >>>>> > >>>>> On Fri, Apr 22, 2016 at 10:52 PM, Matthias Metzger < > >>>>> [email protected]> wrote: > >>>>> > >>>>>> Hi, > >>>>>> > >>>>>> > >>>>>> thanks to all of you for the interest! I just added some examples to > >>> the > >>>>>> README of my repository and implemented an alternative to/enhanced > the > >>>>>> LambdaColumn. Hope this makes your life a little easier. If there is > >>>>>> anything else I can do for that matter, just hit me up. > >>>>>> > >>>>>> > >>>>>> @Carl-Eric: I am very keen to see what you'll come up with. Mapping > >>> over > >>>>>> everything with a <T> was the best I could think of, without > resorting > >>> to > >>>>>> reflection. :D > >>>>>> > >>>>>> Regards, > >>>>>> Matthias > >>>>>> > >>>>>> > >>>>>> ________________________________ > >>>>>> Von: Carl-Eric Menzel <[email protected]> > >>>>>> An: [email protected] > >>>>>> Gesendet: 10:10 Freitag, 22.April 2016 > >>>>>> Betreff: Re: Further Lambda Model ideas > >>>>>> > >>>>>> > >>>>>> Hi Matthias, > >>>>>> > >>>>>> interesting ideas, thank you for sharing! I'm going to have a closer > >>>>>> look either this weekend or next (a bit busy right now). Currently > I'm > >>>>>> working on some Java 8 helpers for Wicket 7, similar to the > LambdaModel > >>>>>> thing currently in WicketStuff. I'm doing that mostly to just play > >>>>>> around with some ideas but also because I'm not entirely happy with > the > >>>>>> WicketStuff LambdaModel - basically I'm exploring to see whether I > can > >>>>>> come up with something I like better. > >>>>>> > >>>>>> Carl-Eric > >>>>>> > >>>>>> > >>>>>> On Thu, 21 Apr 2016 20:19:52 +0000 (UTC) > >>>>>> Matthias Metzger <[email protected]> wrote: > >>>>>> > >>>>>>> Hello everyone, > >>>>>>> I just saw yesterday, that the IModel became/will become a > >>>>>>> @FunctionalInterface in Wicket 8 and was very happy about it. I am > >>>>>>> also very happy about the ongoing implementations and discussions > >>>>>>> around lambda usage in Wicket, because it simplifies a lot of code. > >>>>>>> Now, one thing I have been working on, is implementing some of the > >>>>>>> now known methods of Stream<T> for a AbstractReadOnlyModel and also > >>>>>>> for other things - like columns. I have not seen such discussions > on > >>>>>>> here, please forgive me if I missed that. If it has indeed not been > >>>>>>> discussed and you find the idea useful, you can take a look at an > >>>>>>> implementation in the following repository: > >>> > https://github.com/noobymatze/lambdawicket-model/blob/master/src/main/java/com/github/noobymatze/lambdawicket/model/ReadOnlyModel.java > >>>>>>> What might we be able to do with that? > >>>>>>> Consider a Person containing an Address, containing a Street with a > >>>>>>> name. Now I want to display the name of the street. How would I go > >>>>>>> about that?new Label("streetName", () -> > >>>>>>> person.getAddress().getStreet().getName()); This is one approach, > but > >>>>>>> it completely ignores the possibility of null values and a default > >>>>>>> value for such cases. I could wrap the above in an Optional or > create > >>>>>>> a method in the Person class like 'Optional<String> getStreetName() > >>>>>>> {...}'. > >>>>>>> > >>>>>>> With the proposed ReadOnlyModel I could also do it in the following > >>>>>>> way: new Label("streetName", ReadOnlyModel.of(person). > >>>>>>> map(Person::getAddress). map(Address::getStreet). > >>>>>>> map(Street::getName). orElse("n/a")); But that's not all. Imagine > we > >>>>>>> would need to dynamically truncate the streetName based on user > >>>>>>> input: IModel<WicketFunction<String, String>> truncate = () -> str > -> > >>>>>>> str.length() > 10 ? str.substring(0, 10) + "..." : str; > >>>>>>> IModel<String> truncatedStreetName = ReadOnlyModel.of(person). > >>>>>>> map(Person::getAddress). map(Address::getStreet). > >>>>>>> map(Street::getName). apply(truncate). orElse("n/a"); Now we > >>>>>>> could switch the truncate Model using a > >>>>>>> DropDownChoice<WicketFunction<String, String>> or by just setting > the > >>>>>>> contained function somewhere.truncate.setObject(str -> > >>>>>>> str.substring(0, 20)); > >>>>>>> > >>>>>>> The whole approach is - if I am not mistaken - heavier on memory, > >>>>>>> because instead of one IModel<String> we now have 5 or 6 Models, > that > >>>>>>> cannot be garbage collected, because they are all needed to perform > >>>>>>> the computation. > >>>>>>> > >>>>>>> This doesn't apply for mapping over an IColumn though, because it > >>>>>>> doesn't need to rely on the laziness, like the ReadOnlyModel does > >>>>>>> (otherwise a change in truncate wouldn't mean a change in the final > >>>>>>> value), so:new LambdaColumn(of("Name"), Person::getAddress). > >>>>>>> map(Address::getStreet). map(Street::getName). orElse("n/a")); > >>>>>>> would create 4 new instances of the LambdaColumn, but 3 of them > could > >>>>>>> be gc'd more or less the second they were created - like I said, > if I > >>>>>>> am not mistaken. If this is at all an approach you think might be > >>>>>>> useful, I would be happy to provide the implementation of the > >>>>>>> LambdaColumn. Otherwise just ignore my message. :) Have a nice > >>>>>>> day,Matthias > > >
