missionary

2020-12-21T17:54:13.031100Z

@dustingetz I think the idea of continuous bind makes sense. I've opened an issue https://github.com/leonoel/missionary/issues/26

2020-12-21T17:56:36.032100Z

What is the expected state of discrete bind in missionary today, is that something that is working or close to working do you think?

2020-12-21T17:59:48.033700Z

the 3 discrete bind operators are useful and they're working well

2020-12-21T18:01:58.034600Z

Does it recompute the heights of the nodes when the DAG is adjusted inside a bind-like operation

2020-12-21T18:04:11.035300Z

recompute the heights means what to you ?

2020-12-21T18:05:15.036400Z

C-f for "height"

2020-12-21T18:05:47.036800Z

its the topo ordering mechanic

2020-12-21T18:09:25.037800Z

I'm not sure the ordering strategy is the same

2020-12-21T18:10:22.038400Z

The key sentence is > Bind nodes introduce special height constraints, so that stabilization is guaranteed to recompute the left-hand side of a bind before recomputing any node created by the right-hand side [f]. This avoids recomputing nodes created on the right-hand side that would then become unnecessary when the left-hand side changes. More precisely, in [t >>= f], any node created by [f] is made to have a height larger than [t].

2020-12-21T18:10:45.038900Z

I think I have a failing test case caused by this

2020-12-21T18:11:49.039800Z

reactor has bugs so it's totally possible, I'd love to see your test case though

2020-12-21T18:12:08.040100Z

(tests
  "discrete bind: harder version"

  (def !p (atom 1))
  (def !q (atom 2))
  (def !control (atom :p))

  (def >p (m/watch !p))
  (def >q (m/watch !q))
  (def >control (m/watch !control))
  (def >cross (bind >control (fn [c]
                               (case c :p >p :q >q))))
  (def >z (m/zip vector >p >q >cross))

  (def !z (>z #(println :ready) #(println :done)))

  @!z => [1 2 1]

  (reset! !control :q)
  ; never ready, so below this point is undefined
  ; expected:
  
  @!z => [1 2 2]                                            ; fail
  (reset! !control :p)
  @!z => [1 2 1]                                            ; fail

  )

2020-12-21T18:12:14.040400Z

This is the same as the above test case except

2020-12-21T18:12:27.040600Z

(def >z >cross #_(m/zip vector >p >q >cross))
this line

2020-12-21T18:12:44.040900Z

(defn bind [>a f]
  (ap (?! (f (?! >a)))))

2020-12-21T18:17:59.041300Z

zip with continous flows is weird

2020-12-21T18:18:18.041600Z

what is it supposed to model ?

2020-12-21T18:19:21.042100Z

i don't think zip makes sense in continuous signals

2020-12-21T18:20:16.042900Z

I think about this differently than you, I think in terms of the typeclasses - fmap (variable arity), and bind. I think that's all i need

2020-12-21T18:20:40.043300Z

so just m/latest and bind

2020-12-21T18:22:35.044Z

I think you can emulate continuous bind with (defn bind [>a f] (m/relieve {} (m/ap (m/?! (f (m/?! >a))))))

2020-12-21T18:24:35.045300Z

latest for fmap is fine

2020-12-21T18:25:04.045800Z

Im realizing my test is malformed, i'm mixing continous and discrete primitives again

2020-12-21T18:25:24.046Z

omg it passed

2020-12-21T18:25:29.046500Z

lol

2020-12-21T18:25:37.046700Z

(tests
  "discrete bind: harder version"

  !! (defn bind [>a f] (ap (?! (f (?! >a)))))

  !! (def !p (atom 1))
  !! (def !q (atom 2))
  !! (def !control (atom :p))

  !! (def >p (m/watch !p))
  !! (def >q (m/watch !q))
  !! (def >control (m/watch !control))
  !! (def >cross (bind >control (fn [c]
                                  (case c :p >p :q >q))))
  !! (def >z (m/latest vector >p >q >cross))

  !! (def !z (>z #(println :ready) #(println :done)))

  @!z => [1 2 1]

  !! (reset! !control :q)
  @!z => [1 2 2]         

  !! (reset! !control :p)
  @!z => [1 2 1]         

  )
switched zip to latest and it passes

2020-12-21T18:26:53.047400Z

also your example is a tree, not a dag so I'm not sure how it relates to the height recompute stuff

2020-12-21T18:28:18.048100Z

it's meant to join all signals back together at >z

2020-12-21T18:28:55.048300Z

Using (defn bind' [>a f] (m/relieve {} (ap (?! (f (?! >a)))))) also passed

2020-12-21T18:37:42.050500Z

the height test i think is that the bind-choice (>p or >q) must have a height greater than >control > More precisely, in [t >>= f], any node created by [f] is made to have a height larger than [t].

2020-12-22T09:50:00.050900Z

As I understand it, what matters is that if both t and latest result of f have changed when the value is sampled, t takes priority and f must be recomputed to get a fresh node. Node height is an implementation detail of incremental related to dag propagation order, it's not relevant in missionary because the dag part (`reactor`) is decoupled from flow composition.