Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upSemantics of `fpsWhen` is quite off. #139
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jwmerrill
Jan 24, 2015
Contributor
Good find. I think this points at the need to come up with some good way to
unit test Signal implementations. Especially for the Native code.
Some of these JS APIs make it very easy to make mistakes.
On Sat, Jan 24, 2015 at 11:23 AM Janis Voigtländer notifications@github.com
wrote:
So, in jvoigtlaender/core@274cd7e
jvoigtlaender@274cd7e
I had been trying (as part of the effort to make timestamp work in a
consistent manner over all signals) to refactor fpsWhen while preserving
its semantics. I failed in that, which luckily was caught by @jwmerrill
https://github.com/jwmerrill, and fixed in 6a36cd7
elm-lang@6a36cd7.
Throughout all this, I hadn't been checking what the semantics of fpsWhen
was exactly, only trying to preserve it. Have now looked into the semantics
of fpsWhen and found serious problems, I think.Let's consider a signal isOn with the following behavior:
- initial value False
- at 0.5 seconds, has a True event
- at 2.0 seconds, has a False event
- at 3.5 seconds, has a True event
- at 4.0 seconds, has a False event
- no further events
For example,
isOn = flip member [1,7] <~ keepIf (flip member [1,4,7,8]) 0 (foldp (_ c -> c+1) 0 (every 500))
Let's now consider the signal obtained by fpsWhen 1 isOn. Surprisingly,
it shows the following behavior (since at least Elm-0.13):
- at 0.5 seconds, has an event with value 0
- at around 1.5 seconds, has an event with value 0
- at 2.0 seconds, has an event with value 0
- at around 2.5 seconds, has an event with value around 1000
- at 3.5 seconds, has an event with (same) value around 1000
- at 4.0 seconds, has an event with (same) value around 1000
- at around 4.5 seconds, has an event with value 0
- no further events
One way to check these claims is to run
main = asText << snd <~ foldp ((t',d) (t,l) -> (t',(t'-t,d)::l)) (0,[]) (timestamp (fpsWhen 1 isOn))
(for example with different language versions at http://share-elm.com)
Many of the values we see appearing are dubious (for example, isOn was
True only for 2 seconds overall, and yet we see three time deltas of 1
second each). Also, the events at 2.5 and 4.5 seconds shouldn't be
happening at all. It turns out that the clearTimeout in the
implementation of fpsWhen has no effect whatsoever. PR #138
https://github.com/elm-lang/core/pull/138 fixes that specific "bogus
events" aspect. However, even after that fix, the semantics of fpsWhen is
still off. For the above situation it now behaves as follows:
- at 0.5 seconds, has an event with value 0
- at around 1.5 seconds, has an event with value 0
- at 2.0 seconds, has an event with value 0
- at 3.5 seconds, has an event with value 0
- at 4.0 seconds, has an event with value 0
- no further events
Now the bogus events at 2.5 and 4.5 seconds are gone, but all other events
show value 0, even though the isOn signal has been True for 2 seconds, of
which 1.5 seconds were consecutively, so certainly should have shown some
non-0 time value passing, given that our granularity was "1 frame per
second".—
Reply to this email directly or view it on GitHub
https://github.com/elm-lang/core/issues/139.
|
Good find. I think this points at the need to come up with some good way to Some of these JS APIs make it very easy to make mistakes.
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jvoigtlaender
Jan 25, 2015
Contributor
I've fixed the fpsWhen function, using quite a bit reorganization, in PR https://github.com/elm-lang/core/pull/141.
For the scenario put up above, the behavior of fpsWhen 1 isOn is now as follows:
- at 0.5 seconds, has an event with value 0
- at around 1.5 seconds, has an event with value around 1000
- at 2.0 seconds, has an event with value around 500
- at 3.5 seconds, has an event with value 0
- at 4.0 seconds, has an event with value around 500
- no further events
Which is exactly the sane thing to do, I think. And makes the documentation of fpsWhen true, which says: "The first time delta after a pause is always zero, no matter how long the pause was. This way summing the deltas will actually give the amount of time that the output signal has been running."
|
I've fixed the For the scenario put up above, the behavior of
Which is exactly the sane thing to do, I think. And makes the documentation of |
jvoigtlaender commentedJan 24, 2015
So, in jvoigtlaender@274cd7e I had been trying (as part of the effort to make
timestampwork in a consistent manner over all signals) to refactorfpsWhenwhile preserving its semantics. I failed in that, which luckily was caught by @jwmerrill, and fixed in elm-lang@6a36cd7. Throughout all this, I hadn't been checking what the semantics offpsWhenwas exactly, only trying to preserve it. Have now looked into the semantics offpsWhenand found serious problems, I think.Let's consider a signal
isOnwith the following behavior:FalseTrueeventFalseeventTrueeventFalseeventFor example,
Let's now consider the signal obtained by
fpsWhen 1 isOn. Surprisingly, it shows the following behavior (since at least Elm-0.13):One way to check these claims is to run
(for example with different language versions at http://share-elm.com)
Many of the values we see appearing are dubious (for example,
isOnwasTrueonly for 2 seconds overall, and yet we see three time deltas of 1 second each). Also, the events at 2.5 and 4.5 seconds shouldn't be happening at all. It turns out that theclearTimeoutin the implementation offpsWhenhas no effect whatsoever. PR https://github.com/elm-lang/core/pull/138 fixes that specific "bogus events" aspect. However, even after that fix, the semantics offpsWhenis still off. For the above situation it now behaves as follows:Now the bogus events at 2.5 and 4.5 seconds are gone, but all other events show value 0, even though the
isOnsignal has beenTruefor 2 seconds, of which 1.5 seconds were consecutively, so certainly should have shown some non-0 time value passing, given that our granularity was "1 frame per second".