# BasedPL

> BPL: Based-array Programming Language. APL-derived; J, BQN ideas. Base: Dyalog `⎕ML≥2` (`↑` first/take, `⊃` mix/pick) except below. Most APL idioms don't apply: write BPL.

Entry: Dyalog diff, example, defining page. Not the reference: read the page before relying on an entry. Links relative to https://answerdotai.github.io/basedpl/. Session: `]help ⍳` shows a glyph's or system fn's page.

## Terms

- [Terms](terms.html.md): read fully before reference pages. Includes:
  - atom: non-array: number, char, fn, operator. `5`.
  - scalar: rank-0 array, one value. `⊂5` yes; `5` no.
  - run: glyphs, names, literals, groups, no spaces between. group: code in `[]` `()` `{}`, may hold spaces. runs: `+/÷≢`, `x.[1 2]`.
  - key: string labelling an axis position. not Key `⌸`.

## Language

- [Syntax](syntax.html.md): BQN stranding: mark strands with `[]` (per BQN's 5-year retrospective), except spaced literals (step 1) and subjects side by side (step 3); like BQN, a space is semantic. `⁝` separates tokens and stops literal stranding without ending the run: `h⁝m`≡`h(m)`, `f⍣3⁝0`≡`(f⍣3)0`. 3 steps: 1. spaced literals join, 1 vector: `1 2`, `"ab" "cd"`; even operand+arg: `+/⍠2 3 3 3↕m` has operand `2 3 3 3`, write `+/⍠2 3⁝3 3↕m`. 2. each other run→`(run)`: `a+b × c+d`≡`(a+b)(×)(c+d)`; fn between two runs: space both sides: `a×b + c`≡`(a×b)+c`; `a×b +c`≡`[a×b ; +c]`; `a×b+ c`≡`(a×b+)c`, train `a×(b+c)`; `1+k (⌈/⊢)⌸ a`≡`(1+k)((⌈/⊢)⌸)(a)`. 3. read as APL, right to left; subjects side by side strand: `a b`≡`(a)(b)`≡`[a b]` only if neither touches; `1+a b`≡`(1+a)(b)`→`11 20`, 1 plus both: `1+[a b]`→`11 21`; `n 2⍴0`≡`(n)(2⍴0)`→`[3 [0 0]]`, names never join literal strands: write `[n 2]⍴0`. no needless spaces; join by deleting spaces, not adding parens: `1+k(⌈/⊢)⌸a`. name fn, name arg: `h⁝m` `h[m n]`. name operand, glyph arg: `+/⍠k⍵`. list: `[+/x ; +/x ÷ ≢x]`. name digits: `x_1`; `x1`≡`x(1)`.
- [Evaluation](evaluation.html.md): run ending in fn: train. `+/÷≢ x` mean; `+/÷≢x`≡`+/÷(≢x)`. `⁝` doesn't group a train: `+/÷≢⁝x` still means the latter. A space before an arg makes the run on its left a train: `10÷√1++/⍠i x` calls dyadic `√`, write `10÷√1++/⍠i⁝x`; `+/,m+⍤2 P` applies the train `+/,m+⍤2` to `P`, write `+/,m(+⍤2)P`. Calls give values: a call's result, a field read from it, a subscript's selection and a scope's result bind as arrays even when they hold a function, so `+/÷(f 0)` is an expression, never a train; name a returned function first: `g←f 0 ⋄ +/÷g`; call a selected function with Agenda: `1⍚fs x`, `2 (1⍚fs) 3`.
- [Composition](composition.html.md): read before writing tests or examples. trains: `f⁝g Y`≡`f(g Y)`, `f⁝g⁝h Y`≡`(f Y)g(h Y)`; `∘` atop, `⍥` over, `↣` `↢` bind left, right; `⍨` self, commute; `⊢` `⊣` stand for args in trains; `⁻` inverse; `@` under. worse→better, same results: `0.5×⊢+2÷⊢`→`⊽⁻+÷`; `{⍵,1}`→`,↢1`; `×⍨x`→`x²`; `≥⍣3⊢5`→`≥⍣3⁝5`; `+/⍠i⊢m`→`+/⍠i⁝m`. Prefer spaces for top-level groups/subtrains: `+/÷≢ ⊼v`, `mean_square←+/÷≢ ⊼`, `f⁝g⁝h x`. A space groups the whole left run, including any prefix. Nested `()`: try the inner pair first. Prefer `⁝` where a boundary is needed: `f⍣3⁝0`, `(+/÷≢)⍤1⁝2 3⍴⍳6`; with a left arg too, `Q+.×⍠e⁝r`, or group the derived fn, `10 20(+⍤1)m`: whichever reads better. Keep compound operands grouped: `⌊@(10×)x`. Add nothing where tokens already stay distinct: `+/⍤1m`.
- [Agreement](evaluation.html.md#agreement-and-pervasion): pervasive fns, Each, Rank align leading axes: `[1 2 3⋄4 5 6]+10 20`→`[11 12 13⋄24 25 26]`. length-1 axes expand.
- [Maps](evaluation.html.md#functions-and-effects): Each, Rank, stencils, outer products call a dfn once on all cells where possible: `{⍵×⍵+1}¨v` costs ≈ `v×v+1`. value predicate: each body once, on its cells. output, nested result, value-dependent shape: a call per cell. dfn fold/scan along matrix rows: a call per column, on all rows. `f.g`: dfn `g` once, on all pairings.
- [Arrays](arrays.html.md): numbers, chars, fns: atoms, not scalars (BQN). `⊂` always adds a layer: `⊂3 ≡ 3`→`$f`. array of fns applies to a following subject: `2 [+ ×] 3`→`5 6`.
- [Brackets](glyphs/brackets.html.md): `[a b]` vector, even `[a]`. spaces separate items: `[+/x ÷ ≢x]` 3 items (fn `÷` middle). with `;`, only `;` separates; items are expressions: `[+/x ; +/x ÷ ≢x]` 2 items; `[1 2;3 4]`≡`[(1 2) (3 4)]`. `⋄` rows: `[1 2⋄3 4]` matrix. `"k":v` items: record `["a":1 "b":2]`.
- [Strings](strings.html.md): `"abc"` char vector; `'a'` char atom; `'abc'` error.
- [Indexing](indexing.html.md): no `Y[I]`. `I⌷A` cross product; `A.[I J]` pairs index arrays (NumPy): `i←⍳3ₓ`: `m.[i i]` diagonal. positions from 0; negative from end.
- [Numbers](numbers.html.md): bare number: float (Python `1.`). `3ₓ` [weak](numbers.html.md#weak-and-strong-numbers) machine int, like C/Rust/Swift ints, not an integer-valued float. Dynamic int arithmetic takes the narrowest width holding every result (u8+u8→i16), then wraps at i64; static ints wrap at the selected width. `ₓ₁ ₓ₂ ₓ₄ ₓ₈`: fixed `u8 i16 i32 i64`, wrap. Beside fixed integers, a weak constant literal uses its minimum width (`1ₓ₁+256ₓ` widens); names and formal arguments use their declared kind. `vₓ`: ordinary ints. `3ᵣ`≡`3ᵣ1`: unbounded integer/rational domain, retained even at denominator 1; `1r3`≡`1ᵣ3`. Mixing machine ints with `ᵣ` stays `ᵣ`; mixing floats follows normal float promotion. Bare `∞` and `¯∞` are symbolic bounds: `3ₓ⌊∞`→`3ₓ`. Explicit/computed float infinities promote normally. dynamic default Mathish: `0÷0`→`0` for [Mathish types](terms.html.md#term-mathish-types), tolerant f64 compare; `•prefs ["mathish":$f]` disables both. pervasive float fns within [4 ulp](numbers.html.md#accuracy) of correctly rounded, except those rustymath lists. not promised, vary by platform, run, threads, size, route, spelling: last bits, infinity/NaN results, zero's sign. Algebraic reductions such as `+/` may reassociate; cancellation can change more than the last bits.
- [Scripts](scripts.html.md): `x²`≡`x*2`; numeric `x⁻¹` reciprocal. On functions: `f¹`≡`f⍤1`, `f⁰ ¹`≡`f⍤[0 1]`, `f⁻¹` rank ¯1; bare `f⁻` inverse (`f⁻ ¹` inverse at rank 1). Repeat with `f⍣2`, not `f²`; `v₁`≡`1⌷v`; `a₁ ₂`≡`a.[1 2]`, `a₁₂` index 12, `(a₁)₂` sequential; `f₁ ₂`≡`f⍠[1 2]` selects axes; `nₓ`≡`⌊ₓn`. `ₓ` after fn floors results to machine ints: `7÷ₓ2`→`3ₓ`; `÷ₓ` floors the exact quotient as an ordinary int. `ₓ` after literals floors fractions, saturates infinities: `¯2.5ₓ`→`¯3ₓ`, `1r3ₓ`→`0ₓ`. `ₐ`: `√ ⍟ * ○ ○⁻` give the real part of the principal value: `√ₐ¯4 9`→`0 3`; other pervasive fns convert args to real floats first: `!ₐ25ₓ`→`1.55ₑ25`, `1j2×ₐ1j2`→`1`; non-pervasive fns convert the result (`≢ₐ`); `(3j4)ₐ`→`3`. between names: `xⱼy`≡`x+y×0ⱼ1`; `xₑy`≡`x×10*y`; `xᵣy` constructs a rational from integer components. `vᵣ` converts to the unbounded domain; `÷ᵣ` selects rational division before computing, as `1ₓ÷ᵣ3ₓ`→`1ᵣ3`.
- [Keyed](keyed.html.md): axes have names, keys. `T.a` record field; `⊢.a`≡`{⍵.a}`. arithmetic pairs axes by name: `i←⍳["i":3]`, `j←⍳["j":3]`: `i+j` 3×3.
- [Autodiff](autodiff.html.md): how `∂` works. Integer and `ᵣ` inputs convert to real floats; derivatives are real floats. Complex AD is unsupported. one number in `X`: forward mode, tagged duals. more: one run records linear steps, then reads the Jacobian by transposes or forward runs, whichever fewer: a loss's gradient is one transpose. copies and selections transpose to accumulation. `∂` of a dfn traces a program on the first call with given types and shapes, replayed after: `(•explain t).programs`. a trace stops at effects, random draws, `⍎`, reads of differentiated items (guards, `⍚` selectors), differentiated values inside nested arrays, writes, value-dependent types (dynamic kinds: `√` may give complex, unless its argument is known nonnegative), not shapes: [list](autodiff.html.md#what-stops-a-trace), `(•explain t).stopped`. Opaque inputs supply kind bounds, never narrower numeric contracts. write `∂` and fast code for static kinds, branch and update with approaches like `⍚`, `f@g`, `f@[p]`, `x.[p]←`, not guards; today `⍚` and `@` on differentiated values also stop a trace (planned).
- [Index notation](index-notation.html.md): the formula for one item, run on whole arrays; tacit stays the main style. indices: `[[n i] h]←•index[⍴x ≢b]`; select: `x.[n i]`; contract along an index: `a←7○b.[h]+x.[n i]+.×⍠i⁝w.[i h]`. same index pairs, different indices build a grid: `x.[b k]+.×⍠k⁝w.[k o]`≡`+/⍠k⁝x.[b k]×w.[k o]`≡`x+.×w`, run as a product. read under a new index once `:` removes names: `[q k v]←:z ⋄ k.[b u h j]`. index arithmetic reads as a map: `wo.[j+(≢j)×h d]`.
- [Dfns](dfns.html.md): use a dfn only where a tacit form is longer or clearly awkward: `+/÷≢ v`, not `{+/⍵ ÷ ≢⍵}v`. no tradfns, no `:If` etc. last statement returns. predicate picks body (BQN): `{⍵<0?-⍵;⍵} ¯3`→`3`. absent `⍺` drops out (BQN `𝕨`). operator operands `⍶` `⍹`, not `⍺⍺` `⍵⍵`. `⍢` recursive operator call. error guard kinds as text: `"DOMAIN"::`.
- [Assignment](assignment.html.md): `←` local. modified/selective updates: nearest binding. `[a b]←Y` destructures items by position. repeated position: which value it keeps isn't promised. space before `←`: whole run is target: `[[0 2]]⌷v ←0`.
- [Modules](modules.html.md): `•load "file.bpl"` runs module, gives record of public names. `_` names private.
- [Hanzi](syntax.html.md#hanzi-spellings): hanzi are name chars. leading `•prefs ["hanzi_aliases":$t]` enables aliases: `加总` for `+/`. non-alias hanzi: names. `_` quotes next non-space char into name: `_加_总`.
- [Constants](system/constants.html.md): `$` names: `$t $f $n` true false NaN; `$a` uppercase alphabet; `$d` digits.
- [Style](style.html.md): read before writing BPL. aim: readable to non-APL readers; looking like APL has no value.

## Glyphs

- [Glyphs](glyphs.html.md): every glyph, name. page `glyphs/<name>.html.md`: read before use.
- [Removed](glyphs.html.md#language-wide-differences-from-dyalog-apl): `Y[I]` indexing, `f[A]` axes, `∘.f`, windowed reduce, laminate.
- [`@`](glyphs/at.html.md) Under: `f@g`: `f` on `g`'s selection, written back (BQN `⌾`, not Dyalog `@`): `⌊@(10×)1.25 2.78`→`1.2 2.7`. positions/`[p]`: left arg aligns with right by position, by key if both keyed: `10 20 30 +@[0 2] 1 2 3`→`11 2 33`.
- [`∘`](glyphs/jot.html.md) atop: `⍺ f∘g ⍵`≡`f ⍺ g ⍵` (BQN; Dyalog `⍺ f g ⍵`): `10 -∘| ¯3`→`¯7`.
- [`⍤`](glyphs/jot-diaeresis.html.md) rank, only: `+/¹m` (`+/⍤1 m`) row sums. fn right operand computes ranks.
- [`⍠`](glyphs/quad-colon.html.md) axis: along axes by number or name: `+/⍠0 m`, `+/⍠"month" sales`. options record sets fill: `5↑⍠["fill":¯1] 1 2`→`1 2 ¯1 ¯1 ¯1`.
- [`⌺`](glyphs/quad-diamond.html.md) stencil: Rank over centred windows: `f⌺3 v`≡`f⍤¯1 [¯3]↕v`; `life⌺[3 3] g`≡`life⍤¯2 [¯3 ¯3]↕g`. `f` gets each window alone, no `⍺` (J `;._3`). fn right operand computes window from args.
- [`.`](glyphs/dot.html.md) dot: after array: `.name` field, `.[I]` select. monadic `f.g`: J determinant: `-.×[1 2⋄3 4]`→`¯2`.
- [`⍣`](glyphs/star-diaeresis.html.md) power: count list keeps history: `2×⍣(⍳5) 1`→`1 2 4 8 16`. `f⍣∞` fixed point.
- [`/`](glyphs/slash.html.md) [`⌿`](glyphs/slash-bar.html.md) [`\`](glyphs/backslash.html.md) [`⍀`](glyphs/backslash-bar.html.md): reduce, scan only. left arg: right seed (BQN): `2+/1 2 3`→`8`. `0ₓ₈+/v`: i64 accumulation of fixed bytes, no widened input; `+/vₓ`: ordinary ints. scans run left to right.
- [`⍉`](glyphs/circle-backslash.html.md) transpose: `A⍉Y` sends each axis of `Y` to its destination in `A` (BQN). `A⍉⁻Y` reorders as einops: `["b" "patch":["i" "j"]]⍉⁻y`.
- [`⌷`](glyphs/squad.html.md) index: leading axes: `[[2 0]]⌷10 20 30`→`30 10`. `:` keeps an axis, `∞` the rest, `¯∞` inserts a length-1 axis. `[: 1]`, not `[:1]`.
- [`⊃`](glyphs/right-shoe.html.md) pick: path, a level per item: `[1 2]⊃v` item 2 of item 1.
- [`⍳`](glyphs/iota.html.md) iota: `⍳3`→`0 1 2`; `⍳¯3`→`2 1 0`.
- [`⍸`](glyphs/iota-underbar.html.md) where: dyad: count of items ≤ each value (BQN `⍋`): `1 3 5⍸4 0 5`→`2 0 3`.
- [`=`](glyphs/equals.html.md) classify, [`≠`](glyphs/not-equals.html.md) unique-mask: monadic `=` classifies (J); monadic `≠` marks first of each value: `≠3 1 3 2`→`$t $t $f $t`.
- [`<`](glyphs/less-than.html.md) sort-up, [`>`](glyphs/greater-than.html.md) sort-down: monads sort major cells: `<3 1 2`→`1 2 3`.
- [`≤`](glyphs/less-than-or-equal.html.md) decrement, [`≥`](glyphs/greater-than-or-equal.html.md) increment: `≥3`→`4`.
- [`∨`](glyphs/vee.html.md) real-imag, [`∧`](glyphs/wedge.html.md) polar: monads: J `+.` `*.`.
- [`⊤`](glyphs/down-tack.html.md) [`⊥`](glyphs/up-tack.html.md): digits on last axis (J). monads: binary encode, decode: `⊤5`→`1 0 1`.
- [`∊`](glyphs/epsilon.html.md) [`~`](glyphs/tilde.html.md) [`∪`](glyphs/down-shoe.html.md) [`∩`](glyphs/up-shoe.html.md): compare major cells (BQN). monadic `∩` duplicates: `∩1 2 2 3 3 3`→`2 3`.
- [`⊂`](glyphs/left-shoe.html.md) [`⊆`](glyphs/left-shoe-underbar.html.md): partitions split first axis. `⊂` always encloses, atoms too.
- [`⍷`](glyphs/epsilon-underbar.html.md) groups: monadic: positions grouped by value, as Dyalog `{⊂⍵}⌸`.
- [`≡`](glyphs/equal-underbar.html.md) match: depth unsigned. axis without names or keys matches any.
- [`+`](glyphs/plus.html.md) [`-`](glyphs/minus.html.md): chars take offsets, differences (BQN): `'a'+1`→`'b'`.
- [`○`](glyphs/circle.html.md) cis: monad cis; pi-times is `π`.
- [`÷`](glyphs/obelus.html.md) divide: ints floor, unlike C/Rust/Swift truncation: `1ₓ÷3ₓ`→`0ₓ`, `¯3ₓ÷2ₓ`→`¯2ₓ`. `÷ₐ` float division; `÷ᵣ` rational division; `1ᵣ÷3ᵣ`→`1ᵣ3`. Select the domain before computing. `+/÷≢` remains mean, with the input domain deciding floor, float or rational.
- [`⌹`](glyphs/domino.html.md) matrix divide: singular or wide matrix: least-norm solution, pseudoinverse; Dyalog errors.
- [`⍎`](glyphs/hydrant.html.md) execute: `X⍎Y` evaluates `Y` with record `X`'s keys as names.
- [`⎕`](glyphs/quad.html.md) quad: reading gives a text line; `⍎⎕` evaluates it.
- [`←`](glyphs/left-arrow.html.md) assign: `a⁝f←` with nothing after ≡ `a←f a`.
- [`⍴`](glyphs/rho.html.md) reshape: `⍬⍴Y` rank 0.

## Glyphs Dyalog lacks

- [`¿`](glyphs/inverted-question.html.md) roll: roll, deal (Dyalog `?`). seed: `•prefs ["seed":42]` (Dyalog `⎕RL`).
- [`⊼`](glyphs/wedge-bar.html.md) nand, [`⊽`](glyphs/vee-bar.html.md) nor: Dyalog `⍲` `⍱`. monads square, double: `⊼3`→`9`.
- [`π`](glyphs/pi.html.md) pi-times: `π1`→`3.141592654`.
- [`√`](glyphs/radical.html.md) sqrt: square root, root (BQN): `3√8`→`2`.
- [`⍭`](glyphs/stile-tilde.html.md) primes: J `p:`, other codes. `⍭⁻` counts primes.
- [`⨸`](glyphs/circle-divide.html.md) factors: J `q:`: `⨸360ₓ`→`[2 2 2 3 3 5]ₓ`.
- [`⌻`](glyphs/quad-jot.html.md) polynomials: roots, evaluation (J `p.`): `[1 2 3]⌻2`→`17`. coefficients: `⌻⁻`.
- [`↕`](glyphs/up-down-arrow.html.md) windows: BQN `↕`: `+/3↕1 2 3 4 5`→`6 9 12`. monadic `↕`≡`2↕`. options record pads by edge mode: `["size":3 "edge":"wrap"]↕v`.
- [`#`](glyphs/hash.html.md) replicate: first axis (Dyalog `⌿`): `1 0 2#"abc"`→`"acc"`. monadic: run-length encoding. dyadic `#⁻` expands.
- [`↦`](glyphs/right-arrow-from-bar.html.md) range: `2↦5`→`2 3 4 5`.
- [`:`](glyphs/colon.html.md) keys: `K:Y` attaches keys. `:Y` removes keys, axis names; `⍴Y ⍴ ,Y` keys only.
- [`↣`](glyphs/right-tail-arrow.html.md) before: BQN `⊸`. `a↣f` binds left arg: `2↣×` doubles.
- [`↢`](glyphs/left-tail-arrow.html.md) after: BQN `⟜`. `f↢a` binds right arg: `*↢2` squares.
- [`⊗`](glyphs/circle-times.html.md) outer product: BQN `⌜`, for `∘.f`: `1 2+⊗10 20`→`[11 21⋄12 22]`.
- [`⊘`](glyphs/circle-slash.html.md) valences: `f⊘g`: `f` with one arg, `g` with two (BQN).
- [`⍚`](glyphs/diamond-underbar.html.md) agenda: `selector⍚cases` calls the fn `selector` picks (BQN `◶`). non-unit selector picks per cell: `(0≤)⍚[0 √] ¯4 9`→`0 3`.
- [`⇄`](glyphs/right-left-arrows.html.md) optimize: `cost⇄ start` finds where `cost` is least, searching from `start`. left arg: options.
- [`∂`](glyphs/partial.html.md) derivative: `f∂x`: derivative or Jacobian of `f` at `x`: `⊼∂3`→`6`.
- [`ᵇ`](glyphs/superscript-b.html.md) bitwise: Boolean fn on integer bits: `6∧ᵇ3`→`2ₓ`; `~ᵇ6`→`¯7ₓ`.
- [`⁻`](glyphs/superscript-minus.html.md) inverse: `f⁻`≡`f⍣¯1`; `2×⁻10`→`5`. Bare minus only: `f⁻¹` is rank ¯1, `f⁻ ¹` is inverse at rank 1. `f⁻←g` attaches an inverse.
- [`•`](glyphs/bullet.html.md) system: starts system names: `•json` (Dyalog `⎕NAME`).

## System functions

- [System functions](system-functions.html.md): names ignore case. options: usually keyed left arg. format fn reads, inverse writes: `•json` `•json⁻`. page `system/<name>.html.md`, no `•`: read before use.
- [Text](system-functions.html.md#text): `•c` `•ucs` `•normalize` `•r` `•replace`: `text •r pattern` matches, `text •replace [pattern template]`.
- [Data and files](system-functions.html.md#data-and-files): `•csv` `•json` `•literal` `•vfi` `•date` `•nget` `•nput` `•fetch` `•path` `•metadata` `•readdir` `•copy` `•rename` `•remove` `•mkdir` `•deflate` `•hash` `•uuid`.
- [Display](system-functions.html.md#display): `•element` `•xml` `•svg` `•mime` `•plot` `•image` `•canvas` `•prefs`.
- [Linear algebra](system-functions.html.md#linear-algebra): `•decompose`.
- [Special functions](system-functions.html.md#special-functions): `•special` makes SciPy's gamma, error and beta functions by name: `erf←•special "erf"`.
- [Random](system-functions.html.md#random-numbers-and-distributions): `•rand` `•distribution`.
- [Positions](system-functions.html.md#positions): `•index` `•edge`.
- [Programs](system-functions.html.md#programs): `•load` `•signal` `•storage` `•detach` `•float` `•time` `•host` `•delay`; browser: `•js`.
- [Introspection](system-functions.html.md#introspection): `•nc` `•nl` `•src` `•ex` `•explain` `•memory`.

## Optional

- [Python](python.html.md): `basedpl` package: all of BPL from Python: evaluation, arrays, every fn and operator by name.
- [Web](web.html.md): BPL in a browser; browser build adds `•js`.
