# BasedPL

Assume Dyalog APL with `⎕ML≥2` (`↑` first/take, `⊃` mix/pick), except below. BPL borrows from BQN and J. Use dfns, not tradfns or colon control structures.

## Docs

Links are relative to https://answerdotai.github.io/basedpl/.

- [Glyphs reference](glyphs.html.md)
- [System functions](system-functions.html.md)
- [Syntax](syntax.html.md)
- [Evaluation](evaluation.html.md)
- [Arrays](arrays.html.md)
- [Numbers](numbers.html.md)
- [Superscripts and subscripts](scripts.html.md)
- [Dfns](dfns.html.md)
- [Keyed arrays](keyed.html.md)
- [Assignment](assignment.html.md)
- [Modules and namespaces](modules.html.md)
- [Python](python.html.md)
- Per-glyph: `glyphs/<canonical-name>.html.md`, using names from the glyphs reference.
- System functions: `system-functions.html.md#<name>` without `•`

## Glyph differences

- Removed forms: bracket indexing `Y[I]`, bracket axes `f[A]`, laminate, windowed reduce, outer product `∘.f`, and replicate/expand as functions `/ ⌿ \ ⍀`. These four remain reduction/scan operators.
- Changed functions (monad/dyad): `○` cis/circle; `=` classify/equal (monad as J); `≠` unique-mask/not-equal. Added monads: `∨` real-imag, `∧` polar, `⊼` square, `⊽` double, `≤` decrement, `≥` increment, `⊤` binary-encode, `⊥` binary-decode.
- Added/renamed functions: `⊼` NAND (Dyalog `⍲`); `⊽` NOR (Dyalog `⍱`); `¿` roll/deal (Dyalog `?`); `π` pi-times/pi-ratio; `√` sqrt/root (BQN); `#` replicate first-axis cells, `#⁻¹` expand; `↕` windows (BQN, plus movements/padding); `⍭` primes (like J `p:`, different codes); `⨸` factors (J `q:`); `⌻` roots/polyval (J `p.`, but coefficients come from `⌻⁻¹`); `:` unkey/keyed.
- Changed operators: `∘` atop as BQN, not bind; `⍤` rank only; `⍠` axis by number/name, not Variant.
- Added operators: `↣` before/bind-left (BQN `⊸`), `↢` after/bind-right (BQN `⟜`), `⊗` outer product (BQN `⌜`), `⊘` valences (BQN), `⌾` under (BQN `⌾`), `selector⍚cases` agenda (BQN `◶`), `⇄` explicit inverse pair (J `:.`), `∂` gradient/vector–Jacobian product.
- Different details: `+ -` support character offsets/differences; `∊ ~ ∪ ∩` compare major cells; `⊂ ⊆` partition first axis; `⊤ ⊥` put digits on last axis; depth is unsigned; negative `⍳` counts down; dyadic `⍸` as BQN `⍋`. Reduce supports BQN-style seeds; scans accumulate LTR. Power supports list counts, inverses, `f⍣∞` fixed point and `f⍣[g]` history until.
- `→` is a left-to-right function pipeline, not branch.
- Reading `⎕` gives a line of text, and `⍎⎕` evaluates it.

## Values and notation

BQN's based arrays: numbers, characters and functions are atoms, distinct from rank-0 arrays. Enclose always adds a layer, including around atoms; `⍬⍴Y` makes a rank-0 array. Rank 0 passes atoms as themselves and array items enclosed. APL-style prototypes/fill remain; function fill is the function itself.

`[a b]` is always a vector, even `[a]`. Spaces separate unspaced item expressions; `;` separates expressions containing spaces. `⋄`/newlines stack rows along a new leading axis. In parentheses, rows instead form a nested vector: `(4 ⋄ 4 5)` is `[[4] [4 5]]`. Parentheses without rows only group. Newlines normally mean `⋄`, not continuation.

`"abc"` is a character vector; `'a'` is one character atom. `""` is the empty string. A double-quoted string can span lines, keeping its indentation. Double a double quote inside a string; `'''` is the single-quote character.

Bare numbers are approximate floats. `3ₓ` is an exact integer; `1ᵣ3`/`1r3` an exact rational; `2ⱼ3`/`2j3` complex; `1ₑ¯3`/`1e¯3` an exponent. `[…]ₓ` marks exact literal arrays. Exact integers/rationals grow as needed; mixing with floats becomes approximate. `$t $f $n` are true/false/NaN; `∞ ¯∞` are infinities. IEEE NaN/infinity arithmetic; comparison tolerance `1E¯14`, but grade is exact. Positions, shape, tally and predicates are exact.

`x²` is `x*2`; `f²` is `f⍣2`; `f⁻¹` inverts; `mᵀ` transposes; `fᵘ` encloses a function. `v₁` is `1⌷v`, `v₋₁` selects the last major cell. These postfix marks touch an item, or stand alone after a space to apply to the preceding run. Numeric `ₓ ᵣ ⱼ ₑ` are number markers, not indexing.

Undo and Under follow BQN's inferred-properties spec. Inverse operations are written `f⁻¹`: `1○⁻¹` is arcsine, `⍭⁻¹` counts primes and `•json⁻¹` writes JSON. `f⌾g` writes results back through a `g` that selects. For any other `g` it applies `g⁻¹`.

## Grouping, selection and keys

Spaces group: each unspaced run evaluates first, then runs combine RTL. `a+b × c+d` is `(a+b)×(c+d)`. Literal strands form before runs; names don't join them. A run ending in a function is an APL-style train: `+/÷≢ x` is mean, but `+/÷≢x` is not. A subject before a function binds it: `2×` doubles. An operator takes the whole function on its left and one item on its right; a trailing dyadic operator takes the next run as operand: `⌊⌾ 10× x`. Only spaces build strands: in `f⍣3'b'` and `f⍤1[2 3]`, the touching literal is the argument. Parenthesise a number argument after a number operand.

Names use letters, `∆`, `⍙`; `_` escapes the next character (and following digits). `f2` calls `f`; `f_2` is a name. No BQN casing rules; names take their runtime value's role. Lone `_` discards an assignment.

Positions/axes are fixed 0-origin; negatives count from the end. `I⌷A` takes one selector per leading axis; `[I]⌷v` selects a list of positions on one axis. `∞` selects a whole axis, `¯∞` reverses it. `A.[I J]` is `[I J]⌷A`. Subscripts/dot indexing/selective expressions can be assignment targets.

Pervasion, Each and Rank align leading axes and expand length-1 axes. `K:Y` attaches axis keys; `["a":1 "b":2]` is a record; `T.a` is `"a"⊃T`. Records are BPL's namespaces: `T.(expr)` and `T⍎text` evaluate with the keys of `T` as names, beside the caller's names, and assignments in them stay local. Axes can have names; shape holds those names as keys. Arithmetic pairs named axes and aligns position keys, filling missing entries with prototypes. Unnamed axes align in leading order.

## Dfns, assignment and modules

Dfns return their last statement, not the first unassigned one. `{condition?body;fallback}` uses BQN-style predicates/bodies with one shared scope. Absent `⍺` drops out of expressions as BQN's `𝕨`; `⍺←default` supplies a default. `⍶ ⍹` mark monadic/dyadic operators; `∇` recurses the function, `⍢` the operator. `kinds::handler` guards later errors, naming kinds as text (`"DOMAIN"::`) or `∞::` for all; `$e` is the caught error.

Plain assignment is local; modified/selective updates change the nearest binding. Arrays have value semantics. `T.k←v` replaces or adds key `k`. `[a b]←Y` destructures by position, or by name against a fully keyed record. Local capturing functions cannot outlive their defining call. Bracket items evaluate LTR; function arguments/fork arms RTL.

`•load "file.bpl"` runs a module and returns its public names as a record; `_`-prefixed names are private. `[f]←•load path` imports by name. Each load runs again. `./` and `../` paths are relative to the source file; other relative paths use the working directory.

## System names

`$a` is the uppercase Latin alphabet; `$d` is `"0123456789"`. System functions use case-insensitive `•name`, not `⎕NAME`. Options are generally keyed left arguments.

- Text: `•c •ucs •normalize •r`.
- Data/files: `•csv •json •literal •xml •image •deflate •date •vfi •nget •nput •fetch •hash •uuid`. Filesystem: `•path •metadata •readdir •copy •rename •remove •mkdir`. A format function reads its format, and its inverse writes it. `•json` reads JSON5.
- Display: `•element •svg •mime •plot •prefs`.
- Linear algebra: `•decompose`.
- Programs/introspection: `•load •signal •storage •time •host •delay •nc •nl •src •ex`. `•time 0` is the current Unix time.
- Random: `•rand` makes a seeded generator. `params •distribution name` returns a distribution, and `•distribution name` uses standard parameters where the distribution has them. Each distribution is a record with `sample density cdf quantile` functions.

## Python

The `basedpl` package exposes all of BPL to Python: evaluation, arrays, and every function and operator by name.
