Hi,

I am able to write some docs if the integration is finished.

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
> 

Reply via email to