[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mirage + froc = self-scaling?

Le mardi, 9 avril 2013 Ã 10:16, Richard Mortier a Ãcrit :
> having said all that, to turn your question around, are there strong reasons 
> to prefer React over Froc? i'm still learning about FRP so happy to have 
> discussion about this :)

Well, I'm going to be biased. But here it goes.  

1) I think, that one good property of react is that it's well documented. It 
has a clear denotational semantics [1] and the result of all combinators is 
precisely specified in this semantics. This allows you to easily apply 
equational reasoning to understand the temporal behaviour of your values (an 
example of this is provided in this discussion [2] you may have to move up in 
the discussion to understand what it's about).

2) React has no global data structures. This entails that in presence of 
threads the rules you have to follow are very clear and straightfoward (see 
[3], as already mentioned). It also means that if you have two part of your 
system that use react and are clearly isolated you don't have to do anything to 
ensure correctness.

3) With froc you may leak memory. In fact I was never convinced that it 
wouldn't leak if the breakout.ml example of react's distribution was to be 
implemented in froc, see this [4] message and the following discussion. React 
is leak-free by design, how ever you use it (if it leaks it's a bug). Now it 
relies on Weak arrays to provide this property.

Historically Weak array has been a problem in browsers (which iirc was froc's 
first target). While js_of_ocaml implements weak arrays it *doesn't* implement 
the weak semantics (see this file [5]). This means that as it stands react 
leaks with js_of_ocaml (and more than froc would). In fact I even said myself 
in a casual discussion last friday that froc should be preferred over react in 
the browser because of the lack of Weak array support. However over the 
week-end I decided to challenge this assertion and I would now retract it if 
I'm to look into the future. The reason is that ecmascript 6's proposal has 
WeakMap support (see [6] for current browser support). Unless I'm mistaken it 
is essentially going to be a trivial rewrite of that weak.js file with WeakMap 
to get the correct weak semantics. You will however have to bet on ecmascript 
6's eventual adoption.

4) Regarding the question of control dependencies, it is true that React 
doesn't provide this (though I'm not sure I couldn't be implemented). Since I 
*still* didn't have the time to investigate frp in real system -- hence my 
interest in this discussion -- I won't claim that you do not need this in 
practice but I don't think it's reconcilable with react's semantics as it 
stands and I fear it may betray the idea of frp and lead you on wrong tracks -- 
but I may be wrong or out of touch with reality on that. One thing that strikes 
me in Jake's example [7] is that this:

  let b = x >>= fun x -> return (x = 0)  
  let n0 = x >>= fun x -> return (100 / x)  
  let y = bind2 b n0 (fun b n0 -> if b then return 0 else n0)  

doesn't "work" (may divide by zero). But this  

  let b = x >>= fun x -> return (x = 0)  
  let y = b >>= fun b -> if b then return 0 else x >>= fun x -> return (100 / x)

suddenly does. First note that referential transparency is broken here (similar 
examples exist in react, the semantics tells you why this is the case -- 
signals get only a timeline once they are created -- it seems however more 
prevalent in froc because of these control dependencies).  

This also means that you have two kind of signals in froc, those that are 
defined for all t once created like n0. This is similar to react (to be 
precise, defined at all t until sometime after no longer needed by the system). 
But you also have other kind of signals that have a limited life span, those in 
that else branch, that may be disconnected from the system. It would be 
interesting to actually work out the precise semantics of that but I suspect 
that reasoning about such a system becomes significantly harder since the 
obvious application is to enable/disable side-effects and you no longer have 
obvious timelines for these signals.

What I fear is that this will encourage you to use more side-effecting signals 
in internal nodes of the dependency graph and I really don't think that's a 
good idea. More than once that ended with people emailing me because they 
wanted to control the *order* of updates of side-effecting signals or to update 
primitive signals from an update cycle itself failing to realize that this is 
betraying the very idea of frp where the update are made under a synchrony 
hypothesis [8], everything happens simultaneously, there's no interleaving.  

My take on this (but I have never been able to experiment it) has always been 
that *all* the side effects should be pushed at the boundaries of the frp 
system. Input side effect should drive the primitives (roots of your dag) and 
outputs should be at the leaves of the dag. The idea is that you should really 
treat an update of the graph as a kind of transaction that builds an output 
data structure that you use *after* the update cycle to sort out potential 
conflicts and perform the actual side effects. This allows to isolate the frp 
system, where the semantics can be cleanly applied to reason on the temporal 
domain of your problem, from the messy aspects of the imperative world. 
Unfortunately I have no example to show you and it's a conjecture of mine. But 
to me it seems the only way to envision using frp without betraying the idea 
behind it, that is without loosing its declarative and compositional properties.



P.S. This is not to say that react hasn't it's own problem. It was recently 
pointed to me [9] that signal switching is suboptimal and convoluted at the 
moment in react, but I'm quite confident the solution I mention can be 
implemented. I will try to resolve that as soon as I find an afternoon to 
reabsorb the gist of react's implementation.

[1] http://erratique.ch/software/react/doc/React#sem
[2] https://sympa.inria.fr/sympa/arc/caml-list/2009-12/msg00054.html
[3] http://erratique.ch/software/react/doc/React#update
[5] http://ocsigen.org/darcsweb/?r=js_of_ocaml;a=headblob;f=/runtime/weak.js
[7] http://ambassadortothecomputers.blogspot.co.uk/2010/05/how-froc-works.html
[8] http://erratique.ch/software/react/doc/React#simultaneity
[9] https://sympa.inria.fr/sympa/arc/caml-list/2013-03/msg00030.html



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.