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].
For more options, visit https://groups.google.com/d/optout.