Open achirkin opened 6 years ago
Won't this potentially return different two different values if two different events both ask for the value in the same frame? Also, i'm a bit unclear on why unsafeInterleaveIO is required - why not just compute the value directly?
Yeah, if we want to do this (and it's likely a good idea more generally), we'll need to cache the result of the IO action and make sure it is executed at most once per frame. The unsafeInterleaveIO is likely a little harder to control than we probably want -- the semantics we'd probably want is that the IO action is executed if and when the behaviour is sampled for the first time in a given frame. This is still rather unsafe from the FRP system's standpoint as it lets you distinguish the order in which behaviours are sampled, but for the purpose of writing hosts, you may be able to live with that in many cases. onDemand certainly shouldn't have such a general type -- this is something which ought to live in a subclass of ReflexHost, just to prevent people from stumbling into using it carelessly. I'd also give it a more awkward name, like newPrimitiveBehavior.
As an aside, at various points where the thing I wanted to produce morally had some type like:
(...) => m (Behavior t X)
where the Behavior requires doing some IO to measure something in the external world to compute, I've found that a decent substitute is often to simulate the attach or attachWith for that instead:
(...) => Event t a -> m (Event t (X, a))
(...) => (X -> a -> b) -> Event t a -> m (Event t b)
since this is how you're likely to have consumed the behaviour anyway.
On Thu, 20 Jul 2017 at 17:42 Ryan Trinkle notifications@github.com wrote:
Won't this potentially return different two different values if two different events both ask for the value in the same frame? Also, i'm a bit unclear on why unsafeInterleaveIO is required - why not just compute the value directly?
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/reflex-frp/reflex/issues/122#issuecomment-316838354, or mute the thread https://github.com/notifications/unsubscribe-auth/AGtSbARyXUplXFoVOhyAn3v2j7rMHwJXks5sP8m7gaJpZM4Od-B9 .
Thanks for comments!
Surely, I don't pretend my code snipped should go into the library :) Thanks to unsafeInterleaveIO
, the action happens when the value of Behavior is evaluated to WHNF, which looks totally non-deterministic. However, this is the only trick I found to invalidate an old cache value: PullSubscribed
for a given behavior is created after the action is executed (cause it needs the action result), and unsafeInterleaveIO
ensures invalidate
is called after that (which would be impossible if you evaluated the content of the action to WHNF at the moment of creating PullSubscribed
). Please correct me if this does not make sense!
Now, I am using this workaround in my library to get some really simple state information from JS side of the program, such as whether the CTRL key is pressed at the moment of a click event.
So, until reflex library has some smart way to create such behaviors, I would really like to know if my workaround can potentially break some event/switches due to not taking special care about content of toReconnect
reference. Is that the case?
The point is to be able to run use a cheap
IO a
function to create aBehavior t a
, which would lazily obtain current values whenever any event requires it. I see this question has been answered on stackoverflow from time to time, so I wonder what is the current state of the things?I've been trying to workaround this for a while and came up with a seems-to-be-not-crashing solution. I posted it as an answer to one discussion. Here is how it looks like:
So, the idea is to call
invalidate
function (withunsafeInterleaveIO
) on current state as late as possible every time the value is requested.Now, the question is if this code breaks something internally or not? :) Related questions:
toReconnect
always empty in current setting?WeakList
of invalidators going to be empty in current setting in future?