It is not really about performance but rather about a couple of different 
things that can be solved by this single style.

* I want to not call 'view' until I get done receiving certain data because 
it causes the screen to kind of hemorrhage and flash and it is very jarring 
watching it flicker until the stream is done.
* I want to remove the boilerplate that I keep adding for 
every-single-embedded-component-that-follows-TEA, a central place to 
register their callbacks is quite nice.
* Lazy only works if the data structure is identical (it seems to act like 
a === in javascript), which is highly efficient, but if the data is 
reprocessed due to outgoing sources and did not actually 'change' then it 
does nothing.
* Want a singular area to be able to filter subscriptions to not cause 
events at all if they do not contain the data I want, I hate combining 
filtering and operating over data at the same place, makes it more 
unreadable and although I could separate each message into filtering and 
handling functions, that is a **LOT** of boilerplate, easier to separate 
the concerns and handle each there, significantly less code and a single 
place to see what is happening.
* I already have those style of updates to call components in other 
modules, and they are getting numerous and duplicative.

As well as a few other minor things, mostly I want to remove boilerplate, 
boilerplate of other TEA modules, boilerplate of only handling, say, 
certain keypresses (as in another mailing list conversation that is 
happening, or in my case scroll events, I only want to know certain numbers 
and not get messages every-single-time), just lots and lots of boilerplate 
all over the place that I am seeing get duplicated in huge numbers as the 
programs continue to grow.  Most of these issues could be handled if Elm 
has HKT's, but it does not, so a single callback is the next best thing.

On a side note, I just made a library that fakes this whole process.  I am 
finishing writing some of the States functions then it should be done and I 
will try to fully test it out and do code comparisons in readability and 
size.  Readable code is highly important to me and right now Elm programs 
have far far too much duplicated boilerplate due to lack of HKT's.


On Tuesday, August 9, 2016 at 12:26:22 AM UTC-6, Peter Damoc wrote:
>
> What is this really about? 
> Is it about performance? 
> Do you have bad performance and are thinking that if this would be 
> available you will get better performance? 
>
> Because if this is the case, you could try to create a SSCCE of this bad 
> performance and we could take a look and come up with some solutions. 
>
> What I understood from your request looks like you want smarter 
> functionality when this could be achieved with smarter data structures. 
>
> If you have a lot of NoOp littering your code, think harder about your 
> structures. 
> I doubt that a solution like what you are proposing will not make the code 
> look better, it might just replace the NoOp with States.noChanges.  
>
> You could have your model split in two with one part holding data that is 
> essential to the view and another part holding accidental data. 
> You could then have your main view like: 
>
> view : Model -> Html Msg 
> view model = 
>     lazy mainView model.essential 
>
> you could have the update split the same 
>
> type Msg = Essential EssentialMsg | BookKeeping BookKeepingMsg 
>
> update : Msg -> Model -> (Model, Cmd Msg) 
> update msg model = 
>     case msg of 
>         Essential eMsg -> 
>             let 
>                 (newEssential, cmd) = 
>                     updateEssential eMsg model.essential
>             in 
>                 ({model | essential = newEssential}, cmd)
>
>         BookKeeping bMsg -> 
>             let 
>                 (newBookKeeping, cmd) =
>                     updateBookKeeping bMsg model.bookKeeping 
>             in 
>                 ({model | bookKeeping = newBookKeeping}, cmd)
>
>
> And this is just one of your already available options. 
>
> If you like the blah pattern, you can even implement it as a decorator for 
> the App.program and keep flags and what not in some model together with the 
> user model. 
>
> You have this freedom with the current functionality. 
>
> If there is however an issue of performance that would really be made much 
> better by some changes to the core, then this needs to come with a SSCCE 
> and detailed analysis. 
>
>
>  
>
>
> On Mon, Aug 8, 2016 at 10:20 PM, OvermindDL1 <[email protected] 
> <javascript:>> wrote:
>
>> For note, current work-arounds to lacking the above are things like:
>>
>>    - Handling each no-op messages in the update itself, I have a lot of 
>>    matching cases with no-op `( model, Cmd.none )` all over the place, it is 
>>    ugly and useless
>>    - Various simplifiers in your own code that convert:
>>    ```elm
>>                Helpers helpersMsg ->
>>                    let
>>                        ( helpersModel, helpersCmd ) =
>>                            helpers_update Helpers helpersMsg 
>>    model.helpers
>>                    in
>>                        ( { model | helpers = helpersModel }
>>                        , helpersCmd
>>                        )
>>    ```
>>    Into this:
>>    ```elm
>>                Helpers helpersMsg ->
>>                  convertToMyModel
>>                    (\newModel -> { model | helpers=newModel } )
>>                    ( helpers_update Helpers helpersMsg model.helpers )
>>    ```
>>    Which although shorter and more re-useable is also more unreadable 
>>    (especially due to the lack of something like `put .helpers model`, I 
>> would 
>>    love to know if someone knows a workaround for that, which is shorter and 
>>    more readable than `(\newModel -> { model | helpers=newModel } )`)
>>    - Also do not have to add other TEA module subscriptions to your 
>>    subscriptions, which although a bonus is not a biggie.
>>
>> Much of this could be done via helper libraries that are hooked before 
>> update and subscriptions the view is not so easy to work-around without the 
>> internal library keeping a copy of the view around for when the view does 
>> not want to be called and it could just return it straight, that could 
>> potentially be quite large to be holding another copy of, but it could be 
>> done 'for now' as an example package implementation.
>>
>>
>>
>> On Monday, August 8, 2016 at 1:12:00 PM UTC-6, OvermindDL1 wrote:
>>>
>>> It would be highly useful if there was a way to prevent view, 
>>> subscription, or update from being called while also allowing for module 
>>> transformation for TEA/following modules, which could all be handled via 
>>> adding a single callback (described below) to Program (or a new version 
>>> there-of).  It would require a simple change to the core javascript native 
>>> code (linked below).  Just having Html.lazy on the top view itself is 
>>> insufficient as it does not handle being able to prevent update calls (say 
>>> if the model does not change and no command is raised, useful for view 
>>> update, a rare case and could be ignored in general), being able to prevent 
>>> or filter subscriptions (highly important in many cases, this would allow 
>>> for ignore certain subscription messages, say you are handling input and do 
>>> not want to listen to certain keys or only want to listen to certain keys 
>>> then this would allow you to handle both filtering it as well as 
>>> translating the the filtered data into a new message if wanted all in one 
>>> step), as well as also preventing view updates on a variety of model 
>>> updates (ways that lazy fails badly in is if you are receiving a stream of 
>>> messages from a server, each one is causing a view update, when they are 
>>> incoming as a singular stream and you know when it stops and can turn back 
>>> 'on' rendering at that point, thus completely ignore the view updates for 
>>> the given message stream Message and leave it on for everything else).  You 
>>> could potentially nest lazy's only matching on specific criteria and a 
>>> model variable to define whether it is on or not, but then you have to make 
>>> sure you always turn it on on message types that handle views and turn it 
>>> off only for your specific one, when that really should both be reversed in 
>>> structure and should have no state variable.  Such a callback could also 
>>> handle module transformation for TEA styled handling.
>>>
>>> Thus for the new callback I propose is something like this, called 
>>> `blah` for now since I am bad with naming and do not want to pre-dispose an 
>>> idea of how it should work based on the name:
>>> ```elm
>>>
>>> module main exposing (..)
>>> main : Program ProgramFlagsmain =
>>>     App.programWithFlags
>>>         { init = init
>>>         , blah = blah
>>>         , view = view
>>>         , update = update
>>>         , subscriptions = subscriptions
>>>         }
>>> -- Snip other callback code as they are unchanged
>>> blah : Msg -> ( Msg, States )blah msg =
>>>   case msg of
>>>     MyMessageThree _ -> ( msg, States.batch [ States.cancelView, 
>>> States.cancelSubscriptions ) -- Just preventing certain callbacks
>>>     MyMessageNine arg0 _ -> ( MyMessageThree arg0, States.all ) -- -- Just 
>>> converting a message to another
>>>     MyRedrawMessage -> ( msg, States.onlyView ) -- Just redraw the view, 
>>> unsure if necessary but it is here for completion.
>>>     MyMessageTwelve _ -> ( msg, States.onlyUpdate ) -- Just handle an 
>>> update, subscriptions and view are not called
>>>     OnKeyPress 13 -> ( msg, States.none ) -- Cancel every callback when 
>>> OnKeyPress's value is 13, else it will fall back to the default lower of _ 
>>> that passes through everything unchanged
>>>     OnKeyPress 119 -> ( MoveUp, States.all) -- Convert this specific 
>>> OnKeyPress into a MoveUp message instead, the OnKeyPress vanishes
>>>     MaterialMessage msg -> Material.blah .mdl (\model newMdl -> { model | 
>>> mdl=newMdl } ) msg
>>>     _ -> ( msg, States.noChanges )
>>>
>>> -- Material.blah could be implemented likemodule Material
>>> blah : ( model -> Material.Model ) -> ( model -> Material.Model -> model ) 
>>> -> Material.Msg -> ( Msg, States )blah getModel putModel msg =
>>>   ( msg
>>>   , States.delegate
>>>     { getModel=getModel
>>>     , putModel=putModel
>>>     , update=Material.update
>>>     , subscriptions=Material.subscriptions
>>>     }
>>>   )
>>>
>>> ```
>>>
>>> As you can see it allows but is not restricted to:
>>>
>>>    - Message translation
>>>    - Callback cancellation
>>>    - Message filtering
>>>    - Message filtering and translation
>>>    - TEA models direct update/subscriptions conversion (Just like how 
>>>    you can do `.mdl model` to get `model.mdl`, I wish there were a way to 
>>> do 
>>>    something like `put .mdl model something` and it does `{ model | mdl = 
>>>    something }`, it would make that last second callback more simple)
>>>    - <salesman-voice>And more!
>>>
>>> This solves a variety of issues in but not restricted to:
>>>
>>>    - Simplifying the update to only handle what is actually important
>>>    - Calling view at all only when it is needed (letting you not call 
>>>    it on hot-path messages for example, like when getting a thousand 
>>> messages 
>>>    to fill in something but you don't want to render it until the stream is 
>>>    complete)
>>>    - TEA style inclusion of other modules in a central-include point 
>>>    without needing to pepper crap like this all over your update and more:
>>>    ```elm
>>>    
>>>                Helpers helpersMsg ->
>>>                    let
>>>                        ( helpersModel, helpersCmd ) =
>>>                            helpers_update Helpers helpersMsg model.helpers
>>>                    in
>>>                        ( { model | helpers = helpersModel }
>>>                        , helpersCmd
>>>                        )
>>>    
>>>    ```
>>>
>>>
>>>
>>>
>>> This is my prior post about this:
>>>
>>> I do say that I wish there were some way to make some 'update' call as 
>>> no-view and/or no-subscription re-call needed.  Like instead of returning 
>>> `( model, Cmd.none )` we could do `( model, Cmd.cancelView )` or `( model, 
>>> Cmd.cancelSubscription )` or both via `Cmd.batch`, or perhaps as a 
>>> three-argument tuple that defaults to `( model, Cmd.none, StateChanges.none 
>>> )` or so, which would default to calling everything.  I have a lot of 
>>> update messages that are handled that do not change the view and/or 
>>> subscriptions and it would be nice to prevent calling those somehow.  Hmm, 
>>> actually a backward compatible change would be to add a new Program 
>>> callback, in addition to the usual `init`, `update`, `subscriptions`, and 
>>> `view`, add another one that I will call just `blah` for now, optional in 
>>> the Program or so, but have it be like:
>>> ```
>>> blah : Msg -> ( Msg, States )
>>> blah msg ->
>>>   case msg of
>>>     MyMessageThree _ -> ( msg, States.batch [ States.cancelView, 
>>> States.cancelSubscriptions )
>>>     MyMessageNine arg0 _ -> ( MyMessageThree arg0, States.noChanges ) -- 
>>> or `States.none`?
>>>     MyRedrawMessage -> ( msg, States.cancelView )
>>>     MyMessageTwelve _ -> ( msg, States.onlyUpdate )
>>>     _ -> ( msg, States.noChanges )
>>> ```
>>>
>>> And it would be called after `init` and before every call of `update`.  
>>> It would allow an easy way to translate one message type into another 
>>> (maybe even a way to decorate it more so it can get passed to another 
>>> modules update/subscription, this would be a **great** hooking location for 
>>> modules), as well as a way to specify what states should be updated for a 
>>> given message, a default no-op function could be supplied via 
>>> `States.defaultHandle` or so that you could pass to the program so people 
>>> do not have to override it in the easy cases.
>>>
>>> Hmm, an idea for a module handler, one of the states could be something 
>>> like:
>>> ```elm
>>>     MaterialMessage msg -> ( msg, States.delegate { 
>>> update=Material.update, subscriptions=Material.subscriptions } )
>>> ```
>>> Which of course the other module could simplify via a helper to:
>>> ```elm
>>>     MaterialMessage msg -> Material.blah msg
>>> ```
>>>
>>> Looking at 
>>> https://github.com/elm-lang/core/blob/4.0.4/src/Native/Platform.js 
>>> shows that it would be easy to add that functionality to core.
>>>
>>> So ideas about this style, issues, etc...?
>>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "Elm Discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to [email protected] <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> -- 
> There is NO FATE, we are the creators.
> blog: http://damoc.ro/
>

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to