With regards to the issue that @tom pointed out, let me also suggest that you edit the constructor in the Row class so that it makes new copies of the input arrays, as otherwise you may end up with more hard-to-track-down dependencies in the future. So I would change these lines:
this.values = values;
this.hsla = hsla;
to
// copy array
this.values = values.slice();
// copy once-nested array:
this.hsla = hsla.map(a => a.slice());
This way each Row object gets its own copy of these arrays and running methods on one row object won’t affect the arrays used by other Rows.
Next, I noticed that the evaluation order of some of your cells may not be what you want it to be. Let me be explicit. First, this cell runs:
testRows = makeRows(5, 20, randomHsla(4))
Then, both this cell (the “canvas” cell):
{
const ctx = DOM.context2d(350, 100);
drawRows(testRows, ctx);
return ctx.canvas;
}
and this cell (the “for-loop” cell):
{
for (let i = 0; i < testRows.length; i++) {
testRows[i].changeSaturation(2, 5 * i);
}
}
become able to run. However, the execution order is not guaranteed, and in my tests it looks like the for-loop cell tends to run before the canvas cell when I first load the notebook, but the canvas cell runs first if I re-evaluate the testRows
cell.
In the latter case, after the automatic evaluation finishes, the canvas cell will still show the initial state of testRows
and not what testRows
is after the for-loop cell mutates it, and this might be misleading. Of course, if I then manually evaluate the canvas cell, then I see that the third row of colors has become desaturated, as now it’s drawing the updated testRows
.
If you want the canvas cell to always run after the for-loop, you can name the for-loop cell something:
forLoop = {
for (let i = 0; i < testRows.length; i++) {
testRows[i].changeSaturation(2, 5 * i);
}
}
and then make the canvas cell depend on this as follows:
{
forLoop;
const ctx = DOM.context2d(350, 100);
drawRows(testRows, ctx);
return ctx.canvas;
}