Ah. Sorry. My misunderstanding. I went looking for the Effects.tick
replacement in 0.17+ and only found AnimationFrame.

Mark

On Sun, Dec 11, 2016 at 10:32 PM Janis Voigtländer <
[email protected]> wrote:

> Mark, wow, a lot of material. I’m not able to digest all of it right now.
> But something quick I want to say, because I have the impression that there
> is a misunderstanding about the current state of tick batching support.
>
>
> This:
>
>
>
>
> Since I wasn’t proposing to get rid of subscriptions and since this
> functionality is covered through subscriptions, my proposal arguably
> doesn’t cause a problem.
>
>
>
>
> baffles me. I’m not sure what you mean by “this functionality is covered
> through subscriptions”. Tick batching wasn’t covered through signals (the
> closest predecessors of subscriptions), and isn’t covered through
> subscriptions (or at all!) right now.
>
>
> Specifically and relatedly, concerning this:
>
>
>
>
> The special behavior for tick wasn’t particularly documented for the 0.16
> Effects module and isn’t really documented for the 0.17+ AnimationFrame
> module.
>
>
>
>
> I should clarify that the tick batching trick as existed in the 0.16
> Effects module is *not implemented* for Elm 0.17+. Apparently since gamey
> stuff is not anymore in Elm’s focus, Evan didn’t bring the “first ever
> effect manager” over to the new world when effect managers as such became a
> thing.
>
>
> (Did I indicate previously that tick batching as existed before is a thing
> currently in core or other 0.17/0.18 packages? I don’t think so. I was
> only bringing it up as a thing that can be done with effect managers and
> benefits from, maybe even is absolutely dependent on, having separate
> concepts of Task and Cmd. To decide about maintaining that latter stance,
> will require digesting your material more fully.)
>
>
> ​
>
> 2016-12-11 21:26 GMT+01:00 Mark Hamburg <[email protected]>:
>
> Since I wasn't proposing to get rid of subscriptions and since this
> functionality is covered through subscriptions, my proposal arguably
> doesn't cause a problem. But that's just getting through the loophole of
> this specific example to dodge this particular case, so let me see if I can
> get straight what the special property is that we need to preserve if we
> were still trying to implement a tick command in the same manner of the
> 0.16 tick effect. (It's worth noting as a side note that in 0.16, all
> effects other than tick were tasks, so obviously tasks are close to
> covering the role of commands — née effects — but tick may point to extra
> wrinkles.) I'm not going to assume a constraint by the current task
> implementation, but any revised implementation has to have a clear behavior
> in conjunction with the existing task APIs since its those APIs that make
> tasks an attractive alternative to commands.
>
> The special behavior for tick wasn't particularly documented for the 0.16
> Effects module and isn't really documented for the 0.17+ AnimationFrame
> module. Am I correct that the concern is that when the animation frame
> "arrives":
>
>
>    1. We run all of the update functions before actually calling the view
>    function; and
>    2. Any tick effects that result from those updates will be batched
>    together for the next animation frame
>
> Was there anything else that I'm missing?
>
> The first point means that any implementation is going to have to be built
> in conjunction with the Elm runtime since coordinating with the call of the
> view function requires knowledge of when and how the view function gets
> run. But since the whole point of this is to coordinate with the view
> function that shouldn't be surprising nor is it particularly odd. It does
> mean that my simple example using port tasks wouldn't work because it
> wouldn't enjoy that coordination, but extra requirements add extra
> implementation details.
>
> So, what we want is that we can divide time up with a series of animation
> frame events and at each animation frame event, we want to start a new
> epoch for collecting tick effects, run the updates driven by all effects
> collected for the previous epoch, and then do the view rendering. A naive
> implementation will just keep listening for all animation frames. A more
> sophisticated implementation will take steps to shutdown that observation
> when it is no longer necessary.
>
> The vague handwaving in the above is seemingly around what it means to say
> "run the updates driven by all effects collected for the previous epoch".
> In particular, how does this interact with task chains built using andThen,
> etc.? I am going to make a distinction between two ways to specify
> successor computation on a task. In one case with map the results or the
> error coming from the task to produce a new result or error. In the other,
> we map the results or the error coming from the task to produce a new task.
> I would argue that the first category is what leads to actual messages for
> the model. The second can be viewed as making no changes to the model but
> queueing new task executions.
>
> So, how could this work in a task-based scenario? I'm going to speak of
> tasks initiating and resolving to distinguish between when they have code
> invoked v when they deliver values.
>
> When a tick task initiates, it adds itself to the set of tick task
> executions for the current tick epoch.
>
> When we receive an animation frame call, we do the following:
>
>    1. We grab the contents of the tick epoch set and reset the set to
>    empty
>    2. For each of the tick executions in the tick epoch set grabbed in
>    (1), we resolve the execution using the current time. This means running
>    down the network of tasks chained onto the executions. For cases where we
>    map the result or error to a new result or error, we do so and keep working
>    down the chain. For cases where we map the result or error to a new task,
>    we queue that task for execution.
>    3. We execute the view function.
>
> In this way, we deliver all of the updates that are simply dependent on
> the tick event or a mapping thereof while initiating any further
> computations that were waiting for the tick event.
>
> The other piece of concern is how task queueing works and when tasks get
> to execute. I would probably go for a structure on the task queue in which
> it is also divided into epochs. We process all of the tasks within an
> epoch. Any tasks produced during this processing as a result of andThen,
> etc. go in the next epoch. All tasks produced during an update go in the
> current epoch which we process at the end of the update. This design keeps
> chains of tasks from blocking other update processing. We could go further
> and pull tasks generated by tasks off of a queue that executes even more
> incrementally. The key point is that all of the tasks from an update get
> initiated immediately following the update and tasks initiated from other
> tasks happen as we have time to process them.
>
> In the case of ticks, this means that a tick task that initiates a chain
> will execute immediately following the update but a tick task that is
> initiated from some other task might get run at an arbitrary later time.
> (How arbitrary determines whether we can do things like write Task.tick
> |> Task.andThen (always Task.tick) in order to wait two ticks as opposed
> to at least two ticks.)
>
> To make animation frame updates as efficient as possible, we probably also
> want to avoid draining the task-initiated task queue until after the view
> function is run. That's not critical to the semantics but it could matter
> for performance.
>
> Now, maybe I've missed some other detail that matters, but as I've said
> the documentation for both Effects.tick and AnimationFrame is relatively
> thin on detailed semantics and requirements. But if I've gotten the
> concerns right, then I believe the above shows how a task-based system
> could do what is called for here. Am I missing something? I know I'm
> handwaving through some of the execution machinery, but my intuition from
> writing lots of promise systems in Lua says that this sort of structure
> would work.
>
> Mark
>
> On Sat, Dec 10, 2016 at 10:20 PM, Janis Voigtländer <
> [email protected]> wrote:
>
>
>
> In the case of ticks, what I gather from a read through of the code that
> it does is guarantee that all of the tick requests placed between animation
> frame strobes will all be delivered at the next animation frame strobe. Is
> that a correct read?
>
>
>
>
> Yes, that is a correct read. But no, I don’t think that your post shows
> the same can be done with tasks instead of commands. The reason is, as
> previously mentioned, the existence of andThen for tasks. And your “P.S.”
> does not address this, because you are not there considering what the real
> complication with andThen is. The complication is not whether a tick task
> involved in two andThen chains is run once or twice, the complication is
> how to deal with the “continuations” in those two chains. Let’s look at
> this with some example:
>
>
> In the Effects/Cmd world, using ticks would be like this:
>
>
>
>
>
>    1. At some point, a command tick tagger1 reaches the runtime system,
>    where tagger1 : Time -> Msg for Msg being the program’s message type.
>    The runtime system will not do anything at that point, except for
>    registering in some internal state that a tick request was issued, and that
>    the tagger to use for it is tagger1. So essentially, the runtime
>    system (specifically, the effect manager) at that point stores the function
>    tagger1 in some list.
>
>    2. At some point after that, but before the next animation frame
>    happens, a command tick tagger2 reaches the runtime system. At that
>    point, the effect manager adds the function tagger2 to said internal
>    list.
>
>    3. Some time later, the next animation frame is due. So the runtime
>    system looks at its internal list, sees that there are [tagger1,
>    tagger2], takes the current time stamp t, evaluates msg1 = tagger1 t
>    and msg2 = tagger2 t, and passes msg1 and msg2 to the program’s update
>    function one after the other *but without any intermediate view
>    rendering*. If the update function creates additional
>    effects/commands, the ones created from the calls of update with msg1
>    and msg2 are batched (so that actually the grouping together of
>    updates will propagate to the future).
>
>
>
>
> What about in your hypothetical world in which no Cmd abstraction exists,
> but instead tick has type Task Never Time? Now instead of just using tick
> with functions of type Time -> Msg, tick can be used in task chains, like tick
> |> andThen cont with cont : Time -> Task Never Msg. Let’s look at such a
> scenario:
>
>
>
>
>
>    1. At some point, a task tick |> andThen cont1 reaches the runtime
>    system, where cont1 : Time -> Task Never Msg. As above, the runtime
>    system shouldn’t do anything at that point, except for registering in its
>    internal state that there is this tick request and what to do when it
>    eventually becomes active. The difference to above is that now instead of
>    storing a function Time -> Msg for later use, the system has to store
>    a function Time -> Task Never Msg. Fine enough.
>
>    2. At some point after that, but before the next animation frame
>    happens, a task tick |> andThen cont2 reaches the runtime system,
>    where cont2 : Time -> Task Never Msg. Again, the effect manager should
>    simply add that to the internal list of open tick requests.
>
>    3. Some time later, the next animation frame is due. Now what? The
>    runtime system knows that two tick requests are open. So of course it takes
>    the current time stamp t and passes it to the two functions stored in
>    its internal list. But instead of getting some msg1 : Msg and msg2 :
>    Msg as above, it now gets some task1 = cont1 t : Task Never Msg and task2
>    = cont2 t : Task Never Msg. So *unlike above*, the strategy now cannot
>    be to pass the relevant two messages to the program’s update function
>    while ensuring that no view rendering happens in between (which was the
>    whole point of tick batching in the animation scenario). Because those
>    messages are simply not available right now. What is available are two
>    tasks that when run will eventually return with messages (maybe after some
>    http requests or whatever). So the runtime system can now fire off
>    task1 and task2, but there is no way to tell when they will return,
>    and certainly no assumption can be made that they will return still before
>    the view rendering that is supposed to happen right now because we have an
>    animation frame just due. In consequence, the whole point of tick batching
>    is lost. We don’t get to ensure that groups of update calls get
>    performed “atomically” without intermediate view rendering.
>
>
>
>
> What do you think about the above? To me, it means that in the “just
> tasks” world tick batching as in the “separate tasks and commands” world is
> not possible (with the same quality).
>
>
> ​
>
>
>
>
>
>
>
>
> --
>
>
> 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.
>
>
>
>
>
>
>
>
>
>
>
> --
>
>
> 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.
>
>
>
>
>
>
>
>
>
>
>
> --
>
>
> 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.
>
>
>

-- 
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