for...of

Iterates lazily in row-major order (top to bottom, left to right) over all matching cells in a quadrille. Each iteration yields a cell object of the form { row, col, value }. This pattern mirrors JavaScriptโ€™s for...of, which is used to loop over iterable objects like arrays and generators.

To yield only a subset of cells, use the quadrille cells(filter) method within the loop. The visit(callback, filter?) method offers a concise alternative by applying a callback function to each yielded cell.

Example: Filtering by Value Collection #

(click on canvas to randomize q)

code
Quadrille.cellLength = 50;
let q, hint;

// Emoji sets to populate and filter the quadrille
const monkeys = ['๐Ÿ™ˆ', '๐Ÿ™‰', '๐Ÿ™Š', '๐Ÿฆง'];
const birds = ['๐Ÿ', '๐Ÿฆœ', '๐Ÿฆš', '๐Ÿค'];
// Use spread operator to aggregate arrays
const emojis = [...monkeys, ...birds, '๐Ÿธ', '๐Ÿฏ', '๐Ÿฑ', '๐Ÿถ', '๐Ÿฎ'];

function setup() {
  createCanvas(8 * Quadrille.cellLength, 8 * Quadrille.cellLength);
  highlight();
}

function draw() {
  background('#DAF7A6');
  drawQuadrille(q);
  drawQuadrille(hint);
}

function mousePressed() {
  highlight();
}

function highlight() {
  // Fill the main quadrille q with random emojis
  q = createQuadrille(8, 8);
  // Iterates all cells in q
  for (const { row, col } of q) {
    q.fill(row, col, random(emojis));
  }
  // Create a new quadrille to highlight monkey cells
  hint = createQuadrille(8, 8);
  // Iterates only cells containing monkeys
  for (const { row, col } of q.cells(monkeys)) {
    // Highlight selected cells with translucent black
    hint.fill(row, col, color(0, 140));
  }
}

This example shows two uses of for...of:

  • The first loop (for...of q) iterates all cells in the quadrille to randomly fill them with emojis.
  • The second loop (for...of q.cells(monkeys)) uses a value array filter to select only monkey emoji cells to be highlighted.
    Both loops access the cell { row, col } directly through JavaScript object destructuring.

The spread operator ... is used to combine multiple arrays into one.

const monkeys = ['๐Ÿ™ˆ', '๐Ÿ™‰', '๐Ÿ™Š', '๐Ÿฆง'];
const birds = ['๐Ÿ', '๐Ÿฆœ', '๐Ÿฆš', '๐Ÿค'];
const emojis = [...monkeys, ...birds, '๐Ÿธ', '๐Ÿฏ', '๐Ÿฑ', '๐Ÿถ', '๐Ÿฎ'];

This creates a new array containing all monkey and bird emojis, followed by additional individual emojis.

Example: Filtering by Predicate Value #

(click on canvas to randomize q)

code
Quadrille.cellLength = 50;
let q, hint;

function setup() {
  createCanvas(8 * Quadrille.cellLength, 8 * Quadrille.cellLength);
  highlight();
}

function draw() {
  background('#D6EAF8');
  drawQuadrille(q);
  drawQuadrille(hint);
}

function mousePressed() {
  highlight();
}

function highlight() {
  // Fill q with random ๐Ÿธ, ๐Ÿฏ and ๐Ÿฎ emojis, 15 each
  q = createQuadrille(8, 8).rand(15, '๐Ÿธ').rand(15, '๐Ÿฏ').rand(15, '๐Ÿฎ');
  hint = createQuadrille(8, 8); 
  // Iterate only over filled cells in q using for...of and a predicate filter
  for (const cell of q.cells(Quadrille.isFilled)) {
    // Highlight filled cells with a translucent overlay
    hint.fill(cell.row, cell.col, color(0, 140));
  }
}
The expression q.cells(Quadrille.isFilled) is equivalent to q.cells(value => Quadrille.isFilled(value)). This shorthand works because Quadrille.isFilled already expects a single argument.

Example: Filtering by Predicate Value, Row, and Column #

(move mouse to highlight ๐Ÿธ filled cells in the hovered col, and click to randomize q)

code
Quadrille.cellLength = 50;
let q, hint;

function setup() {
  createCanvas(8 * Quadrille.cellLength, 8 * Quadrille.cellLength);
  // Create q with random ๐Ÿธ, ๐Ÿฏ and ๐Ÿฎ emojis, 15 each
  q = createQuadrille(8, 8).rand(15, '๐Ÿธ').rand(15, '๐Ÿฏ').rand(15, '๐Ÿฎ');
  highlight();
}

function draw() {
  background('#D7BDE2');
  drawQuadrille(q);
  drawQuadrille(hint);
}

function mousePressed() {
  q.randomize();
  highlight();
}

function mouseMoved() {
  highlight();
}

function highlight() {
  hint = createQuadrille(8, 8);
  // Iterate over all ๐Ÿธ cells in the current mouse column
  for (const cell of q.cells({ 
    value: v => v === '๐Ÿธ',    // Only ๐Ÿธ values
    col: c => c === q.mouseCol // Only current column
  })) {
    // Fill the hint cell with translucent black for visual feedback
    hint.fill(cell.row, cell.col, color(0, 140));
  }
}

Syntax #

for(const cell of q)
for(const cell of q(filter))
for(const ({ row, col, value }) of q)
for(const ({ row, col, value }) of q(filter))

Parameters #

ParamDescription
filterRestricts which cells are visited. All cells are included if this parameter is omitted or undefined. It can be:
  • a value collection (Array or Set)
  • a predicate function (value => boolean)
  • an object with optional value, row, and/or col predicates