1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
The end of most analyses is a figure, and figures are where reproducibility quietly dies: a plotting daemon, a font cache, a library version, and yesterday's PNG differs from today's for no scientific reason. Plot renders SVG as a STRING — pure computation, deterministic to the byte: the same program produces the same figure, byte for byte, on any machine, and this page's own build verifies exactly that for the figure below. A figure you can cmp is a figure you can trust in CI.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
expected output:
wrote /tmp/damped.svg, 7847 bytes
The API is the smallest one that earns its keep: ClearFigure, AddLine (xs, ys, colorIndex, label) up to four labelled series, Render (pool, title, xlabel, ylabel) — axes scaled and ticked with the same "nice step" rule everywhere, NaN points simply breaking the line (a gap in the data is a gap in the plot, per chapter 5). RenderHeat does the same for a matrix. The result is a string because chapter 5 already gave us the file boundary: Io.WriteFile, one checked call.
Run here, the figure appears as a link under the output — the sandbox keeps what a cell writes to its /tmp and serves it back. Run locally, open /tmp/damped.svg in any browser. Either way there is no step in which a plotting server, a GUI toolkit or a locale was consulted; the bytes are the bytes.
Eight programs ago the language was a stranger. What you have seen: programs whose imports, widths, failure modes, ownership and thread discipline are all in the source and all checked; a CSV reader that believes the file's documentation instead of guessing; statistics with scipy behind every digit; timeseries whose resolution and convention are data; a chunked-store reader whose use-after-close is uncompilable; and figures that diff. None of it was convenient to write. All of it is convenient to REVIEW — and review, not writing, is where scientific software spends its life.
The reference for every module these chapters used is generated from the definitions themselves (m9c --doc) and ships with the compiler: DynStr, Io, Fmt, Time, Csv, Stats, Mat, Math, Frame, ZarrStore, NetCDF, Parquet, Plot and the rest. The repository's museum/ directory is the language's design rationale in executable form. And every example you just read runs, verbatim, on every commit — if this page and the compiler ever disagree, the build breaks before you can read the lie.