Snapshot / Computational Thinking Repo ↗

Abstraction

Abstraction is the opposite of specialization. A specialized operation cares about the exact thing it works on; an abstract one steps back and works on a shape of data, no matter what's inside.

This is a WebAssembly-native reimagining of MIT's Computational Thinking lesson: the figures below are live WasmMakie islands — drag the sliders and they recompute in your browser, no server.

place (generic function with 1 method)
# ONE function, ANY element type — that is abstraction. It drops `new` into a
# flat (column-major) grid at row i, column j, without caring what `new` is.
function place(new, grid::Vector, i, j, nrows)
	out = copy(grid)
	out[(j - 1) * nrows + i] = new
	return out
end

The same operation, on different types

place doesn't know or care what it's placing. Move the sliders — the same function fills a cell in a grid of numbers and a grid of pixels.

row 1 column 1

# numbers: a flat Int grid with a 5 dropped in (shown column-major).
place(5, fill(1, 12), ai, aj, 3)
# pixels: the SAME `place`, now on a gray grid — a black square at (row, col).
gray_figure(place(0.0, fill(0.85, 12), ai, aj, 3), 3, 4)

One more type — pick a fill

Still the same idea: choose a shade and we fill the whole grid with it, then drop a marker. The operation is abstract over what a "value" even is.

shade

gray_figure(place(0.0, fill(shade, 12), ai, aj, 3), 3, 4)

Why it matters

We wrote place once and it worked for integers and for pixels — we never specialized it to a type. That's the whole game: a language that lets you operate at the level where the operation makes sense, and abstract away the rest.

gray_figure (generic function with 1 method)