

# System functions

A system function is a built-in function whose name starts with
[`•`](glyphs/bullet.qmd), as in `•ucs` or `•json`. Type `•` with Alt-y.
Names are case-insensitive. Many system functions take their options as
a left argument. A function named for a format reads that format, and
its [inverse](scripts.ipynb#superscripts) writes it: `•json` reads JSON,
and `•json⁻¹` writes it. `]help •name` shows the full help for one name.
Built-in values use `$`.

In Python, the workspace object `bpl` has each system function under its
name without `•`. Options become keyword arguments, as in
`bpl.json('{"a": null}', fill=0)`. `.undo` gives the inverse, as in
`bpl.json.undo(Y)` for `•json⁻¹`. [Python](python.ipynb) covers the
calling conventions.

<!-- help -->

## Constants

<!-- help $a -->

### `$a` — Alphabet

`$a` is the uppercase Latin alphabet.

``` bpl
3↑$a               ⍝ "ABC"
$a⍳"CAB"           ⍝ [2 0 1]ₓ
```

<!-- help $d -->

### `$d` — Digits

`$d` is `"0123456789"`.

``` bpl
"a2b"∊$d           ⍝ $f $t $f
```

<!-- help $e -->

### `$e` — Caught error

`$e` is the error that an [error guard](glyphs/error-guard.qmd)’s
handler caught, as a record. The error guard page lists its fields.
Anywhere else, `$e` is a `VALUE` error.

<!-- help -->

## Text

<!-- help •c -->

### `•c` — Case

`•c Y` folds case. `1•c Y` converts to upper case, and `¯1•c Y` to lower
case. A character vector converts as text, with Unicode’s full case
mappings: `ß` becomes `SS`, and a `Σ` that ends a word lowercases to
`ς`. Any other character converts on its own, and stays unchanged when
its mapping has more than one character. Folding converts to upper case,
then to lower case. `•c` keeps the argument’s nesting and leaves items
that aren’t characters unchanged.

``` bpl
•c "AbC"           ⍝ "abc"
1•c "AbC"          ⍝ "ABC"
1•c "straße"       ⍝ "STRASSE"
¯1•c "ΟΔΟΣ"        ⍝ "οδος"
```

<!-- help •ucs -->

### `•ucs` — Unicode

`•ucs Y` converts characters to exact integer code points, and code
points to characters, keeping the shape of `Y`. `E•ucs Y` encodes
characters, or decodes integer code units, where `E` is `"UTF-8"`,
`"UTF-16"` or `"UTF-32"`. The encoding forms take vectors. An invalid
code point or a malformed encoding is a `DOMAIN` error.

``` bpl
•ucs "ABC"         ⍝ [65 66 67]ₓ
•ucs 65 66 67      ⍝ "ABC"
"UTF-8"•ucs 'é'    ⍝ [195 169]ₓ
"UTF-8"•ucs 195 169 ⍝ "é"
```

<!-- help •normalize -->

### `•normalize` — Unicode normalization

`•normalize text` puts text into Unicode normalization form NFC. NFC
uses one code point for a letter and its accent wherever Unicode has
one. `form •normalize text` names the form: `"NFC"`, `"NFD"`, `"NFKC"`
or `"NFKD"`. NFD writes each accented letter as a base letter followed
by combining marks. The K forms also replace compatibility characters,
such as the ligature `ﬁ`, with ordinary ones. An array of strings gives
normalized strings in the same shape.

``` bpl
•ucs "NFD" •normalize "é"   ⍝ [101 769]ₓ
"NFKC" •normalize "ﬁ"       ⍝ "fi"
```

Errors: `DOMAIN` for an unknown form, or an argument that isn’t text.
<!-- help •r -->

### `•r` — Regular expressions

`•r pattern` compiles a Rust regex. It returns a keyed vector of
functions that share the pattern: `match`, `position`, `length`,
`groups` and `replace`. Positions count characters from 0.

`template p.replace text` expands `$0`, `$1`, `${name}` and `$$` in
`template`. Flags go in the pattern, as in `(?i)`. [Regular
expressions](regex.ipynb) covers each function.

Errors: `DOMAIN` for invalid patterns, including look-around and
backreferences, and for non-text arguments; `SYNTAX` for the wrong
valence; `LIMIT` for oversized results.

<!-- help -->

## Data and files

<!-- help •csv -->

### `•csv` — CSV

`•csv text` parses CSV into a vector of columns. Headers become keys.
Numeric columns become numbers. Missing numeric cells become NaN. An
integer column with missing cells stays exact. Missing text cells become
`""`.

`•csv⁻¹ T` writes CSV text for a vector of columns. Keys supply the
header. Column lengths must agree. NaN writes as an empty cell, and so
does the exact value given as `fill`.

Both directions take options on the left: `header`, `separator`,
`quotechar`, `doublequote`, `escapechar`, `decimal`, `thousands`, `trim`
and `fill`. Reading also takes `text_columns`, `numeric_columns` and
`missing`, and writing takes `forcequotes` and `lineending`.
`"forcequotes":2` quotes every field. [CSV](data.ipynb#csv) describes
the options.

Errors: `DOMAIN` for invalid options, duplicate headers, and cells that
CSV can’t hold: nonintegral rationals, complex numbers, functions or
nested cells; `LENGTH` for unequal record widths or columns.

<!-- help •json -->

### `•json` — JSON

`•json text` reads JSON5, which includes all JSON. JSON5 adds comments,
trailing commas, single-quoted strings, unquoted keys, hexadecimal
numbers, `Infinity` and `NaN`. Objects become keyed vectors. Arrays
become vectors. Strings become character vectors. Integers of up to 128
bits stay exact. `true` and `false` become `$t` and `$f`.

`•json⁻¹ Y` writes JSON text. Keyed axes become objects. Unkeyed axes
become arrays. Character vectors become strings. Keyed entries that hold
functions are left out. NaN writes as `null`.

`["fill":v] •json text` reads `null` as `v`. The default is NaN. An
integer array with a `null` stays exact. `["fill":v] •json⁻¹ Y` writes
`v` as `null`. [JSON](data.ipynb#json) covers the conversions.

Errors: `DOMAIN` for malformed JSON, with its line and column, and for
values that JSON can’t hold: an infinity that isn’t `fill`, out-of-range
floats, nonintegral rationals, complex numbers and other functions.

<!-- help •literal -->

### `•literal` — Literals

`•literal⁻¹ Y` writes `Y` as BPL source text, in the notation that
display uses. `•literal text` reads such text back into its value
without running code. The text may hold literals and the functions that
`•literal⁻¹` writes: `⍴`, `⊂`, `,`, `:` and `•ucs`. Nested, keyed and
exact values read back unchanged. `•hash •literal⁻¹ Y` hashes any array.

``` bpl
•literal⁻¹ 2 3⍴⍳6              ⍝ "[0 1 2 ⋄ 3 4 5]"
•literal "[1 [2 3ₓ] ""ab""]"   ⍝ [1 [2 3ₓ] "ab"]
```

Errors: `DOMAIN` when the argument of `•literal⁻¹` holds a function or
an operator, and when the text given to `•literal` holds a name, another
function or more than one value; `SYNTAX` for text that doesn’t parse.
<!-- help •vfi -->

### `•vfi` — Numeric input

`•vfi text` returns two vectors, `[valid numbers]`, for the
whitespace-separated fields of `text`. An invalid field has the flag
`0ₓ` and the value `0`. Fields are parsed as numbers, never executed.

`separators •vfi text` splits on each character in `separators` instead.
It trims whitespace around fields. An empty field is a valid `0`.
[Numeric input](data.ipynb#numeric-input) covers it.

Errors: `DOMAIN` when either argument is not text.

<!-- help •date -->

### `•date` — Dates

`•date text` reads a date and time as a moment: the seconds since the
Unix epoch, midnight UTC on 1 January 1970. Without a pattern it reads
ISO 8601: RFC 3339 text such as `"2024-05-06T10:20:30Z"`, a date and
time with no offset, or a date alone. An array of texts gives an array
of moments. `•time 0` is the current moment.

`•date⁻¹ t` writes the moment `t` as a record of fields named after
chrono’s: `year`, `month`, `day`, `hour`, `minute`, `second`,
`nanosecond`, `weekday` (1 for Monday), `ordinal` (the day of the year)
and `iso_week`. For an array of moments, each field is an array. `•date`
reads such a record back from its first seven fields. A missing month or
day is 1, and a missing time field is 0. `•date` ignores `weekday`,
`ordinal` and `iso_week`.

A pattern on the left reads or writes text in another layout, with
chrono’s strftime specifiers, such as `%Y-%m-%d`. The options are
`pattern`, `zone` and, for `•date⁻¹` only, `locale`. `zone` is `"local"`
or a whole number of seconds east of UTC. It applies to text and fields
without an offset, and is UTC by default. `locale` is a POSIX locale,
such as `"fr_FR"`, for month and weekday names.

``` bpl
•date "2024-05-06T10:20:30Z"                     ⍝ 1714990830
"%d %B %Y" •date⁻¹ 1714990830                     ⍝ "06 May 2024"
["pattern":"%A" "locale":"fr_FR"] •date⁻¹ 0       ⍝ "jeudi"
(•date⁻¹ 0).weekday                               ⍝ 4ₓ
(86400+)⌾("%Y-%m-%d"↣•date) "2024-05-06"          ⍝ "2024-05-07"
```

Errors: `DOMAIN` for text that the pattern doesn’t match, an invalid
date, an unknown field or locale, or an invalid pattern.

<!-- help •nget -->

### `•nget` — Read a file

`•nget path` reads a UTF-8 text file. `•nget "-"` reads the rest of
standard input. A path that starts with `./` or `../` is relative to the
file holding the code, as for [`•load`](#load).

`X •nget path` takes options on the left: `binary` (`1` reads a vector
of byte values) and `encoding` (`"UTF-8"`). [Files](data.ipynb#files)
covers bytes and options.

Errors: `IO` for missing files, invalid UTF-8, other file errors, and
standard input that fails or that the frontend doesn’t provide; `DOMAIN`
for invalid options.

<!-- help •nput -->

### `•nput` — Write a file

`path •nput data` writes `data` to a new file. It returns the number of
bytes written, which isn’t displayed, as with an assignment. Text is
written as UTF-8. An array of numbers is written as bytes, each from 0
to 255, in ravel order. A path that starts with `./` or `../` is
relative to the file holding the code, as for [`•load`](#load).

`"-" •nput data` writes `data` to standard output, with no line ending
added. Text written this way just before a read of `⎕` is that read’s
prompt. See [`⎕`](glyphs/quad.qmd#input).

`X •nput data` takes options on the left: `path`, `overwrite` (`1`
replaces an existing file) and `encoding` (`"UTF-8"`, for text). With
the option `unique`, `•nput` writes a new file with a unique name inside
the directory `path`. It returns the new file’s path, which is
displayed. The option `prefix` sets the start of the name, as for
[`•mkdir`](#mkdir). Plain text on the left is the path.
[Files](data.ipynb#files) covers bytes and options.

Errors: `IO` for an existing file without `overwrite`, and for other
file errors; `DOMAIN` for invalid options or byte values, and for bytes
written to standard output that aren’t UTF-8.

<!-- help •fetch -->

### `•fetch` — Fetch a URL

`•fetch url` requests `url` and returns a record of the response:
`status`, a number; `headers`, a record of text; and `body`, the
response’s text. A missing page gives a result with `status` 404, not an
error. Header names are in lower case, and a repeated header’s values
are joined with `,`. `•fetch` follows redirects. It runs the system’s
`curl`, which must be installed. `•json (•fetch url).body` reads a JSON
response.

`X •fetch url` takes options on the left: `method`, which is `"GET"`, or
`"POST"` with a body; `headers`, a record of text; `body`, text or bytes
to send; and `binary` (`1` gives the body as a vector of byte values).

Errors: `IO` for getting no response, such as for an unknown host or a
refused connection, for a missing `curl`, and for a body that isn’t
UTF-8 without `binary`; `DOMAIN` for invalid options.

<!-- help •path -->

### `•path` — Paths

`•path text` splits a path into a record of its parts, named after
Rust’s: `parent`, `stem`, `extension` and `name`. It never reads the
disk. The option `absolute` first joins a relative path to the working
directory, as Rust’s `std::path::absolute` does, without resolving
links. `•path⁻¹` joins `parent`, `stem` and `extension` into a path, and
ignores `name`. An array of paths gives a record of arrays.

``` bpl
•path "data/sales.csv"                            ⍝ ["parent":"data" "stem":"sales" "extension":"csv" "name":"sales.csv"]
{⍵.extension←"tsv" ⋄ ⍵}⌾•path "data/sales.csv"   ⍝ "data/sales.tsv"
```

Errors: `DOMAIN` when a path isn’t text, for an unknown part, or for an
`absolute` path that is empty or has no working directory to join.

<!-- help •metadata -->

### `•metadata` — File metadata

`•metadata paths` gives a table with a row for each path, as a record of
columns. The columns follow Rust’s `std::fs::Metadata`:

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr>
<th>Column</th>
<th>Gives</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>path</code>, <code>name</code></td>
<td>The path as given, and its last part</td>
</tr>
<tr>
<td><code>kind</code></td>
<td><code>"file"</code>, <code>"dir"</code>, <code>"symlink"</code> or
<code>"other"</code>, or <code>"none"</code> for a path that doesn’t
exist</td>
</tr>
<tr>
<td><code>target</code></td>
<td>For a symbolic link, the path it points to, as Rust’s
<code>std::fs::read_link</code> gives it. Empty for any other entry</td>
</tr>
<tr>
<td><code>len</code></td>
<td>The size in bytes</td>
</tr>
<tr>
<td><code>modified</code>, <code>accessed</code>,
<code>created</code></td>
<td>Moments, in seconds since the Unix epoch, as <a
href="#date"><code>•date</code></a> reads them. NaN where the system
records none</td>
</tr>
<tr>
<td><code>readonly</code></td>
<td>Whether the permissions forbid writing</td>
</tr>
<tr>
<td><code>hidden</code></td>
<td>Whether the name starts with <code>.</code></td>
</tr>
<tr>
<td><code>readable</code>, <code>writable</code>,
<code>executable</code></td>
<td>Whether this process may read, write or execute the entry</td>
</tr>
<tr>
<td><code>uid</code>, <code>mode</code>, <code>owner</code></td>
<td>On Unix only: the owner’s numeric ID, the mode bits and the owner’s
name</td>
</tr>
</tbody>
</table>

A symbolic link’s kind is `"symlink"`. Its other columns describe the
entry it points to.

Errors: `DOMAIN` when a path isn’t text.

<!-- help •readdir -->

### `•readdir` — List a directory

`•readdir dir` gives the table of [`•metadata`](#metadata) with a row
for each entry of `dir`, sorted by path. Each row’s `path` is `dir`
joined with the entry’s path within `dir`. A glob on the left keeps the
entries whose path within `dir` matches it, as in
`"*.csv" •readdir "data"`. As in a shell, `*` stays within one directory
and `**` crosses them. Options on the left: `glob`, and `recurse` (`1`
also lists the entries of subdirectories).

Errors: `IO` for a directory that can’t be read; `DOMAIN` for an invalid
glob or option.

<!-- help •copy -->

### `•copy` — Copy

`to •copy from` copies the file `from` to `to`, or the directory `from`
with everything in it. It returns `to`, which isn’t displayed. A copied
file replaces an existing file at `to`.

Errors: `IO` for file errors, such as a missing `from` or a missing
parent directory of `to`.

<!-- help •rename -->

### `•rename` — Rename

`to •rename from` moves `from` to `to` and returns `to`, which isn’t
displayed. Both must be on the same filesystem.

Errors: `IO` for file errors.

<!-- help •remove -->

### `•remove` — Remove

`•remove path` removes a file or an empty directory, and returns `path`,
which isn’t displayed. With the option `recurse`, as in
`["recurse":1] •remove path`, it removes a directory and everything in
it.

Errors: `IO` for a missing path, a directory that isn’t empty without
`recurse`, and other file errors; `DOMAIN` for an invalid option.

<!-- help •mkdir -->

### `•mkdir` — Make a directory

`•mkdir path` makes the directory `path` and any missing parents, and
returns `path`, which isn’t displayed. With the option `unique`, it then
makes a directory with a new, unique name inside `path`, and returns
that directory’s path, which is displayed, as in
`["unique":1] •mkdir •host "temp"`. The option `prefix` sets the start
of the name, as in `["unique":1 "prefix":"run"] •mkdir dir`. The
directory stays until removed.

Errors: `IO` for file errors; `DOMAIN` for an invalid option, or
`prefix` without `unique`.

<!-- help •deflate -->

### `•deflate` — Compression

`•deflate bytes` decompresses gzip data and returns the bytes.
`•deflate⁻¹ data` compresses `data` with gzip. It compresses text as
UTF-8, and numbers as bytes from 0 to 255, as [`•nput`](#nput) writes
them. Both directions take a format name on the left: `"gzip"`, `"zlib"`
or `"deflate"` (raw DEFLATE).

``` bpl
•ucs •deflate •deflate⁻¹ "hello"          ⍝ "hello"
"zlib" •deflate "zlib" •deflate⁻¹ 1 2 3   ⍝ [1 2 3]ₓ
```

Errors: `DOMAIN` for an unknown format, byte values outside 0 to 255, or
data that doesn’t decompress.

<!-- help •hash -->

### `•hash` — Hashing

`•hash data` gives the SHA-256 digest of `data` as 64 hexadecimal
digits, as tools such as `sha256sum` print it. Text is hashed as UTF-8,
and numbers as bytes. `alg •hash data` uses `"sha224"`, `"sha256"`,
`"sha384"` or `"sha512"`.

``` bpl
•hash "abc"   ⍝ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
```

Errors: `DOMAIN` for an unknown algorithm, or byte values outside 0 to
255.

<!-- help •uuid -->

### `•uuid` — UUIDs

`•uuid v` returns a new UUID of version `v` as text. Version 4 is
random. Version 7 UUIDs begin with their creation time and sort in
creation order. Version 0 is the nil UUID, with every digit zero.
Versions 1 and 6 also hold the time, with a random node in place of a
MAC address.

`[ns name] •uuid 5` derives a UUID from a name with SHA-1, and
`[ns name] •uuid 3` with MD5. `ns` is `"dns"`, `"url"`, `"oid"`,
`"x500"` or a UUID. The same namespace and name always give the same
UUID. `bytes •uuid 8` makes a UUID from 16 bytes, and sets its version
and variant.

``` bpl
["dns" "python.org"] •uuid 5   ⍝ "886313e1-3b8a-5372-9b90-0c9aee199e5d"
```

Errors: `DOMAIN` for any other version, or a left argument that doesn’t
fit the version.

<!-- help -->

## Display

<!-- help •element -->

### `•element` — XML elements

`•element tag` returns an element function for the XML tag `tag`. Call
it with attributes on the left and children on the right, as in
`["r":10] circle ""`. An empty right argument, `""` or `⍬`, gives no
children. The result is a keyed vector with `tag`, `attrs` and
`children` entries. Notebooks display it as HTML. [XML and
SVG](xml.ipynb) covers element trees.

Errors: `DOMAIN` for invalid tag or attribute names.

<!-- help •xml -->

### `•xml` — XML text

`•xml text` reads XML into an element tree with the same meaning.
Attribute values become text. Names keep their prefixes, and namespace
declarations become `xmlns` attributes. Comments, processing
instructions and text that is only whitespace are dropped. [XML and
SVG](xml.ipynb) covers element trees.

`•xml⁻¹ tree` writes the XML text of an element tree. It escapes `&`,
`<`, `>` and `"` in text and attribute values. A numeric vector
attribute becomes space-separated numbers. Children are text, elements
or vectors of children. An element with no children closes itself.

``` bpl
•xml⁻¹ •xml "<a href=""x"">hi</a>"   ⍝ "<a href=""x"">hi</a>"
```

Errors: `DOMAIN` for malformed XML, and for invalid names or attribute
values given to `•xml⁻¹`.

<!-- help •svg -->

### `•svg` — SVG pictures

`X •svg children` returns an `svg` element with attributes `X`. It adds
`xmlns` for the SVG namespace and `viewBox="0 0 100 100"`. Attributes in
`X` replace these. Notebooks display it as a picture. [XML and
SVG](xml.ipynb) covers element trees.

<!-- help •mime -->

### `•mime` — Rich display

`•mime Y` returns the MIME bundle that display uses for `Y`. The bundle
is a keyed vector from MIME types to text, or to bytes for a binary type
such as `image/png`. It always has `text/plain`. If `Y` has a renderer,
`•mime` calls it with `Y` as `⍵` and adds its entries.

`F •mime Y` returns `Y` with the renderer that `F` holds, as in
`{["text/html":"<b>",(⍕⍵),"</b>"]}ᵘ •mime Y`. A MIME type on the left
displays `Y` itself as that type, as in `"text/markdown" •mime "*hi*"`.
An atom becomes a scalar, because only an array can hold a renderer.

A result keeps a renderer when it has an item for each item of its
argument, as pervasive functions, Each and scans do. Rearranging or
selecting from an array without removing an axis also keeps it, as
reversal, transpose, take, replicate and catenation do. Changes in place
keep it. Other functions drop it, as reductions and `⍴` do. When two
arguments have different renderers, the result has none. Match ignores
renderers.

Display shows the text form when a renderer fails. Only a direct `•mime`
call reports the error. [Rich display](xml.ipynb#rich-display) covers
renderers.

Errors: `DOMAIN` for a left argument that holds neither a function nor
text.

<!-- help •plot -->

### `•plot` — Plots

`X •plot Y` returns a plot spec: a keyed vector holding the data `Y` and
the settings `X`. Its renderer displays the spec as an SVG chart. Plain
text on the left is shorthand for `mark`. [Plots](plot.ipynb) shows each
mark and setting with examples.

The structure of `Y` chooses the series and axes:

- A vector plots its values against `0…n-1`.
- A keyed vector of numbers uses its keys as x labels.
- A matrix plots one series per row. Row keys name the series. Column
  keys label x.
- With the `cell` mark, each row of a matrix is a row of cells, coloured
  by value. Row keys label the rows, and row 0 is at the top.
- A table, a keyed vector of equal-length columns, plots each column as
  a series. A column named `x` supplies the x values.
- A vector or matrix of plots draws a figure.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th>Setting</th>
<th>Holds</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>mark</code></td>
<td><code>"line"</code>, <code>"point"</code>, <code>"bar"</code> or
<code>"cell"</code></td>
<td><code>"line"</code></td>
</tr>
<tr>
<td><code>title</code></td>
<td>Chart title</td>
<td>none</td>
</tr>
<tr>
<td><code>width</code>, <code>height</code></td>
<td>Size in pixels</td>
<td><code>600</code>, <code>400</code></td>
</tr>
<tr>
<td><code>x</code>, <code>y</code></td>
<td><code>title</code>, <code>scale</code> (<code>"linear"</code> or
<code>"log"</code>), <code>ticks</code>, and <code>axis</code>
(<code>$f</code> hides that axis)</td>
<td></td>
</tr>
<tr>
<td><code>legend</code></td>
<td><code>position</code> (<code>"end"</code> or a corner) and
<code>border</code></td>
<td>none</td>
</tr>
<tr>
<td><code>grid</code></td>
<td><code>$f</code> hides the grid lines</td>
<td><code>$t</code>, or <code>$f</code> for cells</td>
</tr>
<tr>
<td><code>axes</code></td>
<td><code>$f</code> hides both axes, with their ticks and titles. An
<code>axis</code> setting in <code>x</code> or <code>y</code> overrides
it for that axis</td>
<td><code>$t</code></td>
</tr>
<tr>
<td><code>flip</code></td>
<td><code>$t</code> swaps the axes</td>
<td><code>$f</code></td>
</tr>
<tr>
<td><code>palette</code></td>
<td>Colours for numbers: <code>"viridis"</code>, <code>"gray"</code>, or
a list of colours</td>
<td><code>"viridis"</code></td>
</tr>
<tr>
<td><code>colorbar</code></td>
<td><code>$t</code> shows the colour scale beside the plot</td>
<td><code>$f</code></td>
</tr>
<tr>
<td><code>color</code>, <code>size</code>, <code>labels</code></td>
<td>Styles for every series</td>
<td></td>
</tr>
<tr>
<td><code>series</code></td>
<td>Styles for one series, keyed by its name</td>
<td></td>
</tr>
<tr>
<td><code>widths</code>, <code>heights</code>, <code>share</code></td>
<td>Figure cell sizes and shared axis ranges</td>
<td></td>
</tr>
</tbody>
</table>

`color` also takes one number per point. `palette` turns these numbers
into colours, over the range of every series in the plot. A cell takes
its colour from its own value unless `color` is set.

A direct [`•mime`](#mime) call on a spec reports these errors: `DOMAIN`
for unknown settings or values, and for cells mixed with other marks;
`LENGTH` when series, colours, sizes or labels don’t match the x values;
`RANK` for data that isn’t a vector, matrix or table.

<!-- help •image -->

### `•image` — Images

`•image Y` returns a picture: numbers from 0 to 1, with axes for rows,
columns and up to four channels, that notebooks display as an image. One
channel is grey, and three are red, green and blue. A second or fourth
channel is alpha. `Y` is the path of a PNG or JPEG file, the bytes of
one, or the numbers themselves. Values outside 0 to 1 are clipped when
the picture is displayed or encoded.

`•image⁻¹ Y` encodes the picture `Y` as PNG bytes, and
`"jpeg" •image⁻¹ Y` as JPEG bytes. JPEG drops alpha. [`•nput`](#nput)
writes the bytes to a file, as in `"out.png" •nput •image⁻¹ Y`.

Errors: `DOMAIN` for an unknown `kind`, invalid image bytes, or values
that aren’t real numbers; `RANK` for a shape that isn’t a picture; `IO`
for file errors.

<!-- help •prefs -->

### `•prefs` — Display settings

`•prefs Y` applies the settings in the record `Y` to this session’s
display, and returns every setting. `•prefs ⍬` changes nothing.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th>Setting</th>
<th>Holds</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>box</code></td>
<td><code>$t</code> draws arrays in boxes</td>
<td><code>$t</code> in the REPL and the BPL Jupyter kernel,
<code>$f</code> elsewhere</td>
</tr>
<tr>
<td><code>trees</code></td>
<td><code>$t</code> shows a function as a tree while <code>box</code> is
on</td>
<td>as <code>box</code></td>
</tr>
<tr>
<td><code>fns</code></td>
<td><code>$f</code> leaves output made inside functions unboxed</td>
<td>as <code>box</code></td>
</tr>
<tr>
<td><code>limit</code></td>
<td>The most items display shows in full. <code>∞</code> shows every
item</td>
<td><code>1000</code></td>
</tr>
<tr>
<td><code>edges</code></td>
<td>Positions shown at each end of a long axis</td>
<td><code>3</code></td>
</tr>
<tr>
<td><code>prec</code></td>
<td>Significant digits shown for each float. <code>∞</code> shows every
digit</td>
<td><code>∞</code></td>
</tr>
<tr>
<td><code>width</code></td>
<td>The widest line display shows. <code>∞</code> allows any width</td>
<td>The terminal’s width in the REPL, <code>∞</code> elsewhere</td>
</tr>
</tbody>
</table>

Display shows part of an array of more than `limit` items: the first and
last `edges` positions of each axis longer than twice `edges`. `…`
replaces the hidden columns, `⋮` the hidden rows, and `⋱` sits where
they cross. A nested array follows the same rule on its own. A line
wider than `width` hides columns in the same way, keeping as many at
each end as fit. `⎕←`, [`⍕`](glyphs/format.qmd) and source text always
hold every item and every digit.

Errors: `DOMAIN` for an unknown setting or an invalid value.

<!-- help -->

## Linear algebra

<!-- help •decompose -->

### `•decompose` — Matrix decompositions

`kind •decompose m` factors the matrix `m` and returns the factors as a
record. `kind` names the decomposition:

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th><code>kind</code></th>
<th>Fields</th>
<th>Factors</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"svd"</code></td>
<td><code>u</code>, <code>s</code>, <code>v</code></td>
<td><code>m</code> is <code>(u×⍤1 s)+.×+⍉v</code>, with the singular
values <code>s</code> in descending order</td>
</tr>
<tr>
<td><code>"qr"</code></td>
<td><code>q</code>, <code>r</code></td>
<td><code>m</code> is <code>q+.×r</code>, with orthonormal columns in
<code>q</code>, and <code>r</code> upper triangular</td>
</tr>
<tr>
<td><code>"eigen"</code></td>
<td><code>values</code>, <code>vectors</code></td>
<td>each column of <code>vectors</code> is an eigenvector of
<code>m</code>, for the eigenvalue at the same position in
<code>values</code></td>
</tr>
<tr>
<td><code>"cholesky"</code></td>
<td><code>l</code></td>
<td><code>m</code> is <code>l+.×+⍉l</code>, with <code>l</code> lower
triangular</td>
</tr>
</tbody>
</table>

The SVD and the QR decomposition are thin. For an `r`-by-`c` matrix, `u`
and `q` have `r⌊c` columns. The factors are floats. A real matrix gives
real factors, apart from complex eigenvalues and their eigenvectors. A
Hermitian matrix, one equal to its conjugate transpose, has real
eigenvalues in ascending order and orthonormal eigenvectors.
[`⌹`](glyphs/domino.qmd) solves linear systems.

``` bpl
("svd" •decompose 3 2⍴1 2 3 4 5 6).s     ⍝ 9.525518091565104 0.5143005806586441
("eigen" •decompose 2 2⍴2 1 1 2).values  ⍝ [1 3]
```

Errors: `RANK` for an argument that isn’t a matrix; `LENGTH` for
`"eigen"` or `"cholesky"` of a matrix that isn’t square; `DOMAIN` for an
unknown decomposition, an empty or nonnumeric matrix, or `"cholesky"` of
a matrix that isn’t Hermitian positive definite.

<!-- help -->

## Random numbers and distributions

<!-- help •rand -->

### `•rand` — Generator

`•rand seed` returns a generator: a keyed vector of two functions that
draw from one stream of random numbers. The seed is a nonnegative
integer. The same seed gives the same draws.

- `roll Y` works like `¿Y`.
- `X deal Y` works like `X¿Y`.

A distribution’s `sample` takes a generator on its left, as in
`g d.sample 3`. Copies of a generator share its stream. Drawing from one
copy moves every copy on.

Errors: `DOMAIN` for a seed that is not a nonnegative integer, or a left
argument to `sample` that is not a generator; `LENGTH` or `RANK` for
more than one seed; `SYNTAX` for a dyadic call to `•rand`.

<!-- help •distribution -->

### `•distribution` — Distributions

`params •distribution name` returns the distribution called `name`, with
parameters `params`. `•distribution name` uses the distribution’s
standard parameters, listed in the table below. A distribution is a
keyed vector of four functions:

- `sample shape` draws random values. `g sample shape` draws them from a
  generator made by `•rand`.
- `density x` gives the probability density, or the probability mass for
  a discrete distribution.
- `cdf x` gives P(X ≤ x).
- `quantile p` inverts the CDF.

``` bpl
d←•distribution "normal"
d.cdf 0                         ⍝ 0.5
b←10 0.5 •distribution "binomial"
b.quantile 0.5                  ⍝ 5ₓ
```

Parameters are finite real units or vectors. Scale, shape, rate and
degrees of freedom are positive, except where stated.
[Distributions](distributions.ipynb) shows them in use.

<table>
<colgroup>
<col style="width: 33%" />
<col style="width: 33%" />
<col style="width: 33%" />
</colgroup>
<thead>
<tr>
<th>Name</th>
<th>Parameters</th>
<th>Standard</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"normal"</code></td>
<td>μ σ: mean, standard deviation</td>
<td>0 1</td>
</tr>
<tr>
<td><code>"uniform"</code></td>
<td>a b: lower and upper bounds, a &lt; b</td>
<td>0 1</td>
</tr>
<tr>
<td><code>"bernoulli"</code></td>
<td>p ∈ [0,1]</td>
<td></td>
</tr>
<tr>
<td><code>"binomial"</code></td>
<td>n p: integer trials n ≥ 0, p ∈ [0,1]</td>
<td></td>
</tr>
<tr>
<td><code>"poisson"</code></td>
<td>λ ≥ 0: mean</td>
<td></td>
</tr>
<tr>
<td><code>"beta"</code></td>
<td>α β: shapes</td>
<td></td>
</tr>
<tr>
<td><code>"gamma"</code></td>
<td>k θ: shape, scale, with mean kθ</td>
<td></td>
</tr>
<tr>
<td><code>"inversegamma"</code></td>
<td>α β: shape, scale, with density ∝ x⁻⁽ᵅ⁺¹⁾ exp(−β/x)</td>
<td></td>
</tr>
<tr>
<td><code>"exponential"</code></td>
<td>λ: rate, with mean 1/λ</td>
<td>1</td>
</tr>
<tr>
<td><code>"chisquared"</code></td>
<td>ν: degrees of freedom</td>
<td></td>
</tr>
<tr>
<td><code>"student"</code></td>
<td>ν: degrees of freedom, with location 0 and scale 1</td>
<td></td>
</tr>
<tr>
<td><code>"fisher"</code></td>
<td>ν₁ ν₂: degrees of freedom</td>
<td></td>
</tr>
<tr>
<td><code>"cauchy"</code>, <code>"laplace"</code>,
<code>"logistic"</code></td>
<td>location, scale</td>
<td>0 1</td>
</tr>
<tr>
<td><code>"lognormal"</code></td>
<td>μ σ: mean and standard deviation of log(X)</td>
<td>0 1</td>
</tr>
<tr>
<td><code>"weibull"</code></td>
<td>k λ: shape, scale</td>
<td></td>
</tr>
</tbody>
</table>

Errors: `DOMAIN` for an unknown name, a name that isn’t a string, a
monadic call for a distribution with no standard parameters, invalid
parameters, non-real inputs or p ∉ \[0,1\]; `LENGTH` for the wrong
number of parameters; `RANK` for matrix parameters or shapes; `SYNTAX`
for a dyadic call to `density`, `cdf` or `quantile`; `LIMIT` for
oversized shapes or sampler ranges.

<!-- help -->

## Programs

<!-- help •load -->

### `•load` — Load

`•load path` runs the BPL file at `path` as a [module](modules.qmd),
with names of its own. It returns a record of the module’s public names:
the names its top level assigns that don’t start with `_`. The file adds
no names to the caller, and shows nothing except explicit output. Each
call runs the file again.

Destructure the record to take names, as in `[a b]←•load path`, or keep
it and read names with a dot, as in `m←•load path` and then `m.a`.

A path that starts with `./` or `../` is relative to the file holding
the code. Other relative paths are relative to the working directory.
`•nget` and `•nput` follow the same rule.

Errors: `IO` for a file that can’t be read; `DOMAIN` for a file that
loads itself, directly or through other files.

<!-- help •signal -->

### `•signal` — Signal

`•signal kind` raises an error of the kind that `kind` names, and
`message •signal kind` gives it a message. Without one, the message is
“explicitly signalled”. An [error guard](glyphs/error-guard.qmd) catches
the error in the same way as an error from a primitive.

``` bpl
positive←{⍵≤0?"must be positive" •signal "DOMAIN";⍵}
safe←{"DOMAIN"::0 ⋄ positive ⍵}
safe¯3    ⍝ 0
safe4     ⍝ 4
```

`kind` is the name of one of BPL’s kinds, which the error guard page
lists, or any other one-word name, which makes a kind of the program’s
own. Names are read in any case. `kind` can also be a caught error, such
as `$e`, and `•signal` raises its kind and message again at the
`•signal` call.

Errors: `DOMAIN` for a number, or a name that isn’t one word of letters,
digits and underscores.

<!-- help •storage -->

### `•storage` — Storage

`•storage Y` names the storage that holds the items of `Y`: `"boolean"`,
`"integer"`, `"float"`, `"complex"`, `"character"` or `"mixed"`. An atom
gives its own kind, which can also be `"rational"` or `"function"`.
Compact storage holds items of one kind. `"integer"` covers integers of
every width. Mixed storage keeps each item’s kind. Boxed display marks
the same storage on its bottom edge. [Storage](numbers.qmd#storage)
describes each storage.

<!-- help •time -->

### `•time` — Timing

`•time t` gives the seconds since the moment `t`. Moments count seconds
from the Unix epoch, as [`•date`](#date) reads and writes them.
`•time 0` is the current moment. `t←•time 0` starts a timer, and
`•time t` then gives the seconds since it started.

`F •time x` calls each function in `F` on `x` for about 0.1 s. The
result is each function’s fastest time per call in seconds, with the
shape and keys of `F`. With `F←["sum":+/ "max":⌈/]`, `F •time x` labels
each time. Time a dyadic function with its left argument bound, as in
`2↣⍴`. [Timing](repl.qmd#timing) has examples.

Errors: `DOMAIN` for a left argument that holds anything but functions,
or a `t` that isn’t a number. An error from a timed function stops the
timing.

<!-- help •host -->

### `•host` — Host facts

`•host name` gives the host fact called `name`.

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<thead>
<tr>
<th>Name</th>
<th>Gives</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"args"</code></td>
<td>The arguments after the program on the command line, as a vector of
strings. <code>bpl prog.bpl a b</code> gives <code>"a" "b"</code></td>
</tr>
<tr>
<td><code>"version"</code></td>
<td>BPL’s version</td>
</tr>
<tr>
<td><code>"env"</code></td>
<td>The environment variables, as a record of strings</td>
</tr>
<tr>
<td><code>"width"</code></td>
<td>The width of the terminal that output goes to, or <code>⍬</code>
without one</td>
</tr>
<tr>
<td><code>"height"</code></td>
<td>The height in lines of the terminal that output goes to, or
<code>⍬</code> without one</td>
</tr>
<tr>
<td><code>"cwd"</code></td>
<td>The working directory</td>
</tr>
<tr>
<td><code>"temp"</code></td>
<td>The directory for temporary files</td>
</tr>
</tbody>
</table>

Errors: `DOMAIN` for any other name.

<!-- help •delay -->

### `•delay` — Delay

`•delay s` pauses for `s` seconds and returns the seconds it actually
waited, which aren’t displayed. An interrupt stops it, and `•delay ∞`
waits for one.

Errors: `DOMAIN` for a negative number of seconds, or an `s` that isn’t
a number.

<!-- help -->

## Introspection

<!-- help •nc -->

### `•nc` — Name class

`•nc names` gives the class of each name: `¯1` invalid, `0` undefined,
`2` value, `3` function, `4` operator. A character vector names one
binding. An array of strings keeps its shape.
[Introspection](introspection.ipynb) has examples.

<!-- help •nl -->

### `•nl` — Name list

`prefix •nl classes` lists the visible user names in `classes` that
begin with `prefix`, as a sorted vector of strings. `•nl classes` lists
them all. [Introspection](introspection.ipynb) has examples.

Errors: `DOMAIN` for unsupported classes; `RANK` for a class matrix.

<!-- help •src -->

### `•src` — Source

`•src name` returns the definition text of a function or operator,
including comments. [Introspection](introspection.ipynb) has examples.

Errors: `VALUE` for an undefined name; `DOMAIN` for an array.

<!-- help •ex -->

### `•ex` — Erase

`•ex names` erases the nearest binding of each name. An outer binding
can then become visible. It returns `1` when the name is gone, and `0`
for an invalid or protected name. [Introspection](introspection.ipynb)
has examples.
