On Sun, Apr 24, 2016 at 11:13 PM, Matthias Metzger <
[email protected]> wrote:

> And it would actually reduce the API, since we can achieve the same using
> #map, so in my opinion you could probably throw it out entirely. :)
>

I'd prefer to remove it for now.
If we see a need we could re-add it later.
Thank you for all the help!


>
>
>
>
> ----- Ursprüngliche Message -----
> Von: Matthias Metzger <[email protected]>
> An: "[email protected]" <[email protected]>
> Gesendet: 23:10 Sonntag, 24.April 2016
> Betreff: Re: Further Lambda Model ideas
>
> In Haskell land it would be the implementation of an Applicative. Now the
> apply is just like the #map-method, which would make them duplicates, if I
> am not mistaken. It could mainly be used to dynamically update the value
> contained inside the model. So if I have some sort of Model containing an
> implementation of a Function, I might do stuff like this:
>
> WicketFunction<Integer, Integer> square = (x) -> x * x;
>
>
> IModel<WicketFunction<Integer, Integer>> model = () -> (age) -> age + 10;
>
> Person matthias = new Person("Matthias", 24);
>
> IModel<Integer> matthiasAge = IModel.of(matthias).
>   map(Person::getAge).
>   apply(model);
>
> matthiasAge.getObject() // => 34
>
> model.setObject(square);
> matthiasAge.getObject() // => 48
>
>
> The same could be achieved in this way:
> IModel<Integer> matthiasAge = IModel.of(matthias).
>   map(Person::getAge).
>   map(age -> model.getObject().apply(age));
>
> I personally like the first one a little better, but that's probably down
> to opinion.
>
>
>
>
>
> ----- Ursprüngliche Message -----
> Von: Martin Grigorov <[email protected]>
> An: "[email protected]" <[email protected]>
> CC: Matthias Metzger <[email protected]>
> Gesendet: 22:44 Sonntag, 24.April 2016
> Betreff: Re: Further Lambda Model ideas
>
> I've removed IModel from the type of the parameter of #apply():
>
> https://git1-us-west.apache.org/repos/asf?p=wicket.git;a=commitdiff;h=506ada45;hp=268bce97f173e5a2ee2f2f7d734a0c35c9ee960d
> Please let me know if the IModel is really needed for something.
>
> Martin Grigorov
> Wicket Training and Consulting
> https://twitter.com/mtgrigorov
>
>
> On Sun, Apr 24, 2016 at 10:34 PM, Martin Grigorov <[email protected]>
> wrote:
>
> > Unfortunately #flatMap() is still not what I'd like it to be.
> >
> > @Test
> > public void flatMap()
> > {
> >    IModel<String> heirModel = IModel.of(person).flatMap(person1 -> new
> > Model<String>() {
> >       @Override
> >       public String getObject()
> >       {
> >          return person1.getName() + " is my parent";
> >       }
> >    });
> >    assertThat(heirModel.getObject(), is(equalTo("John is my parent")));
> >
> >    String newValue = "New Value";
> >    heirModel.setObject(newValue);
> >    assertThat(heirModel.getObject(), is(equalTo(newValue)));   // << THIS
> > FAILS
> > }
> >
> > the new value is set on a *fresh* instance of "new Model". I.e. it goes
> to
> > /dev/null
> >
> > Martin Grigorov
> > Wicket Training and Consulting
> > https://twitter.com/mtgrigorov
> >
> > On Sun, Apr 24, 2016 at 9:14 PM, Martin Grigorov <[email protected]>
> > wrote:
> >
> >>
> >> On Sun, Apr 24, 2016 at 8:51 PM, Sven Meier <[email protected]> wrote:
> >>
> >>> Hi Martin,
> >>>
> >>> that's quite nice to have these methods in IModel actually.
> >>>
> >>> Java 8 default methods to the rescue :)
> >>>
> >>
> >> The only method impl that bothers me is #flatMap().
> >> I've made it non-lazy to be able to return the produced IModel<R>.
> >> I have to see how other Monad impls do it.
> >>
> >>
> >>>
> >>> 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
> >>>>>>>>>
> >>>>>>>>
> >>>
> >>
> >
>

Reply via email to