Scalars, Vectors & Matrices
A thermostat shows one number, a receipt shows a line of them like `[3.50, 2.20, 1.80]`, and a spreadsheet shows a whole grid. Same digits, but the layout alone decides what they mean and which ones your code can combine.
- ▸The same three numbers mean different things as a single reading, a line, or a grid, layout is the message.
- ▸Resize a block of numbers and one tag changes; edit a value and it doesn't. That gap is the idea.
- ▸Two blocks that disagree on a size, with neither side equal to 1, get rejected before any math runs.
A thermostat reading is one number: 72. A grocery receipt is a line of numbers, one per item: [3.50, 2.20, 1.80]. A spreadsheet, or a grayscale photo, is a grid: numbers filling rows and columns. These are three different ways to hold numbers, and the difference is not the numbers themselves. It is how many of them there are and how they are laid out.
That layout carries meaning the digits alone cannot. 72 on its own is a temperature. Put it in a line next to two other readings and it becomes one entry in a series. Arrange readings in a grid and each one now has both a row and a column that say what it describes.
The panel below shows all three side by side and names each one. Build each layout yourself: drop in a single number, stretch it into a line, then add a second line to make a grid. The name above each block is doing real work. It is the first thing any numerical library reports about your data, and it decides what that data is even allowed to do next.
You just built three blocks and read a tag like (3) or (2, 3) above each. That tag is the shape: for a vector it is the length of the line, for a matrix it is the number of rows then the number of columns, written as a pair. A single number's shape is empty, (), there are no directions to count.
Here is the part worth slowing down for. Change a number inside a block, turn a 3.50 into a 99, and the shape tag does not move. The values are free to be anything. Now grab the edge of the block and resize it: add an entry, drop a row. This time the shape tag is the only thing that reacts.
So shape is not about which numbers you hold. It is about the frame that holds them: how many slots, arranged in how many directions. This is why you can state a shape without reading a single value, and why (2, 3) and (3, 2) are different frames even when the six numbers inside are identical. Every numerical library prints this frame first, because most of what a block is allowed to do next is decided by its shape, not its contents.
Take a line of three numbers, a set of (x, y, z) coordinates, say [4, 1, 9]. Lay it across, left to right, and its shape is (1, 3): one row, three columns. Stand the same three numbers upright, one per line, and the shape becomes (3, 1): three rows, one column.
Same three values. Same order. Different shape. The lying-down version and the standing-up version are not interchangeable, and this trips up almost everyone at first, because the numbers look identical. What changed is which direction counts as along the list.
The move that swaps one for the other is a flip: rows become columns, columns become rows. A (1, 3) becomes a (3, 1); a (2, 4) grid becomes a (4, 2) grid. The values are carried along untouched, only the frame turns. Watch which slot a chosen number lives in before and after: it moves from the top row to the left column. Getting fluent with this flip now is what keeps the later habit of reading A[1][0] versus A[0][1] from ever feeling ambiguous.