In most array languages, m[1, :] hands you something — a view in
numpy, a copy in MATLAB, and in either case a bug when you guessed wrong.
Mica refuses the roulette outright: a verb whose name says copy answers
a fresh value, always, and the borrowing twin has its own names on the
spans page.
The example is
examples/Slicing.
Build and run it:
make -C examples/Slicing runThe copy verbs
r := Row(m, 1); { one row of a 3x4, as a vector of 4 }
c := Column(m, 2); { one column, as a vector of 3 }
corner := SubMatrix(m, 1, 2); { a rectangle; its SHAPE is the target's }
run := Window(r, 1); { SubMatrix in one dimension }The result shapes come from declared types, so a row of a
matrix[3, 4] of float64 is a vector[4] of float64 — checked at
compile time. SubMatrix reads its rectangle’s shape off the assignment
target: corner declares 2×2, the call names only the origin. Four value
parameters, two sources, one generics deduction.
Column is a copy on purpose: a column of a row-major matrix is strided
storage, and the three-word view cannot say so honestly — so there is no
ColumnView to lie with, and the copy is the honest verb.
Independence, proven
r[0] := 999.0;
WriteLn(" after r[0] := 999, m[1, 0] is still %lf", m[1, 0]); { 10.000000 }The example edits the copy and prints the original — not a promise, a demonstration.
The constructors
ramp := Range(1.0, 2.0); { start + k * step, one rounding per element }
eye := Identity(); { the eye, numpy's rectangular rule }
m := MatrixFill(1.5);
v := Fill(2.0);All target-bound: the declared type on the left tells the call its shape,
the same imposition every factory call reads. A constructor buried inside
another call has no target to read — Exp(Fill(0.0)) is refused with the
written-out escape named (5209 … 'Fill of int64 (...)') — which is the
imposition’s honest boundary, not a gap.
Guards, not clamps
Every verb guards its contract: an origin or index that does not fit panics with the contract named — the same loud answer at every optimization tier, never a clamp, never a wrap. The harness pins the panic’s file and line through every tier including full optimization.
What this does not do
- No bracket slicing sugar.
v[lo..hi]is exactly where the roulette lives in other languages; the named forms carry the semantics first. Sugar can come later — semantics cannot be retrofitted. - No strided views.
ColumnViewwould need a fourth word and its own design look; recorded, not smuggled. - No allocation-free copies. A copy allocates its value on the stack like any Mica value; when you want zero copies, say so — that verb family is the span’s.
Try it
Declare corner : matrix[2, 3] of float64 instead and watch the same
call return a different rectangle — the target is the shape. Then ask for
SubMatrix(m, 2, 3) and meet the guard panic with its contract named.
Next
The borrowing twins — RowView, WindowView, and the span of T value
they answer — are the spans page.