Multiple mutables and an interactive view

Here’s a dilemma I encountered while making a little sketch today:

Suppose you want to make an interactive SVG sketch, in which you can drag a number of dots around, and then perform additional operations on the coordinates of these dots. So, we have the data: interactive SVG sketch svg, and dot coordinates a, b, c. There are a number of ways to doing this ‘Observable-style’ (instead of putting everything in a single big cell):

  1. Make cells for a, b and c, and then let svg depend on these. We won’t be able to update a, b and c from within svg though.

  2. Make a, b and c mutable, so that we can update them from within svg. This is good, except that if you want to make all nodes draggable with a single call to say d3.drag().on("drag", ondrag), then you can’t really choose dynamically which of the mutables to update, because of the syntacticality of the semantics of mutable. The best you can do is something like:

    function ondrag (d) {
      switch (d.key) { // check which point we're dealing with
        case 'a': mutable a = ...; break;
        case 'b': mutable b = ...; break;
        ...
      }
    }
    
  3. So, we would have to combine the cells in a single mutable, say mutable abc = {a: ..., b: ..., c: ... }, and then we can write something like

    function ondrag (d) {
      const data = mutable data;
      data[d.key] = ...;
      mutable abc = data;
    }
    

    This is actually very reasonable, but especially in the case that we have an unspecified number of dots. If we know we have say 3 or 6 dots or so (as in my own doodle) and want to talk about them specifically, them this can get cumbersome and awkward.

  4. A final option would be to make the SVG a view of the node’s data: viewof abc = { ... }, however, a drawback here is that we can’t have the SVG be interestingly dependent (and hence recomputed) on other cells anymore insofar as we want to save our values of abc between these recomputes of svg (now dubbed viewof abc).

I settled for option (3) today, but this gets a bit cumbersome when, say, you want to interactively edit three triangles with each 3 dots, and have to pack it all into a single mutable cell.

The general dilemma here, is how to setup a cycle of interactivity between a determinate number of reactive datapoints (hopefully cells) and an interactive cell, and specifically the awkwardness of being able to write complex mutable-setting logic (see 2 and 3), although in essence mutable-setting is a single-cell operation (maybe mutable-setting should be rethought?).

Not looking for an answer, just bringing it up as an example of a notebook-writing dilemma’s :slight_smile:

1 Like

Actually, option (3) works perfectly well. You group all relevant data into a mutable m, and then write update handlers like so:

function ondrag (d) {
  (mutable m)[i][j].x[d.k] = ... // complex assignments to m
  d[0] = ...; d[1] = ...; ...    // ..or using existing references
  mutable m = mutable m;  // <- for reactivity
}

… not really sure why I thought this was such a point :wink:

(A part of me would want all kinds of sugar such as being able to write a cell mutable [a, b] = [.., ..] and subsequently update it with mutable a = ..., but this is just that: sugar, and not really necessary at all.)

1 Like