aboutsummaryrefslogtreecommitdiff
path: root/docs/spec
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2021-08-11 17:21:31 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2021-08-11 17:25:04 -0400
commit2afb23928e1984d475cc460e1672e8f6fa0e4dbe (patch)
treeebd2cc514294d30b6fa4b36c2ee638326f06ef72 /docs/spec
parenteac61ca02074c218667754d5f4ef562e780bae85 (diff)
Allow clicking on header to get fragment link
Diffstat (limited to 'docs/spec')
-rw-r--r--docs/spec/evaluate.html8
-rw-r--r--docs/spec/grammar.html2
-rw-r--r--docs/spec/index.html2
-rw-r--r--docs/spec/inferred.html30
-rw-r--r--docs/spec/literal.html2
-rw-r--r--docs/spec/primitive.html34
-rw-r--r--docs/spec/scope.html12
-rw-r--r--docs/spec/system.html22
-rw-r--r--docs/spec/token.html2
-rw-r--r--docs/spec/types.html2
10 files changed, 58 insertions, 58 deletions
diff --git a/docs/spec/evaluate.html b/docs/spec/evaluate.html
index 044f534c..2d1e5ce9 100644
--- a/docs/spec/evaluate.html
+++ b/docs/spec/evaluate.html
@@ -4,22 +4,22 @@
<title>Specification: BQN evaluation</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-evaluation">Specification: BQN evaluation</h1>
+<h1 id="specification-bqn-evaluation"><a class="header" href="#specification-bqn-evaluation">Specification: BQN evaluation</a></h1>
<p>This page describes the semantics of the code constructs whose grammar is given in <a href="grammar.html">grammar.md</a>. The formation rules there are not named, and here they are identified by either the name of the term or by copying the rule entirely if there are several alternative productions.</p>
<p>Here we assume that the referent of each identifier, or equivalently the connections between identifiers, have been identified according to the <a href="scope.html">scoping rules</a>.</p>
<p>Evaluation is an ordered process, and any actions required to evaluate a node always have a specified order unless performing them in any order would have the same effect. Side effects that are relevant to ordering are setting and getting the value of a variable, causing an error, and returning (with <code><span class='Gets'>β†’</span></code>) from a block. Errors described in this page are &quot;evaluation errors&quot; and can be caught by the Catch (<code><span class='Modifier2'>⎊</span></code>) modifier. For caught errors and returns, evaluation halts without attempting to complete any in-progress node, and is restarted by Catch (for errors) or at the end of the appropriate block evaluation (for returns).</p>
-<h3 id="programs-and-blocks">Programs and blocks</h3>
+<h3 id="programs-and-blocks"><a class="header" href="#programs-and-blocks">Programs and blocks</a></h3>
<p>The result of parsing a valid BQN program is a <code><span class='Function'>PROGRAM</span></code>, and the program is run by evaluating this term.</p>
<p>A <code><span class='Function'>PROGRAM</span></code> or <code><span class='Function'>BODY</span></code> is a list of <code><span class='Function'>STMT</span></code>s, which are evaluated in program order. A result is always required for <code><span class='Function'>BODY</span></code> nodes, and sometimes for <code><span class='Function'>PROGRAM</span></code> nodes (for example, when loaded with <code><span class='Function'>β€’Import</span></code>). If any identifiers in the node's scope are exported, or any of its statements is an <code><span class='Function'>EXPORT</span></code>, then the result is the namespace created in order to evaluate the node. If a result is required but the namespace case doesn't apply, then the last <code><span class='Function'>STMT</span></code> node must be an <code><span class='Function'>EXPR</span></code> and its result is used. The statement <code><span class='Function'>EXPR</span></code> evaluates some APL code and possibly assigns the results, while <code><span class='Value'>nothing</span></code> evaluates any <code><span class='Value'>subject</span></code> or <code><span class='Function'>Derv</span></code> terms it contains but discards the results. An <code><span class='Function'>EXPORT</span></code> statement performs no action.</p>
<p>A block consists of several <code><span class='Function'>BODY</span></code> terms, some of which may have an accompanying header describing accepted inputs and how they are processed. An immediate block <code><span class='Value'>brImm</span></code> can only have one <code><span class='Function'>BODY</span></code>, and is evaluated by evaluating the code in it. Other types of blocks do not evaluate any <code><span class='Function'>BODY</span></code> immediately, but instead return a function or modifier that obtains its result by evaluating a particular <code><span class='Function'>BODY</span></code>. The <code><span class='Function'>BODY</span></code> is identified and evaluated once the block has received enough inputs (operands or arguments), which for modifiers can take one or two calls: if two calls are required, then on the first call the operands are simply stored and no code is evaluated yet. Two calls are required if there is more than one <code><span class='Function'>BODY</span></code> term, if the <code><span class='Function'>BODY</span></code> contains the special names <code><span class='Value'>𝕨𝕩𝕀</span><span class='Function'>π•Žπ•π•Š</span></code>, or if its header specifies arguments (the header-body combination is a <code><span class='Modifier'>_mCase</span></code> or <code><span class='Modifier2'>_cCase_</span></code>). Otherwise only one is required.</p>
<p>To evaluate a block when enough inputs have been received, first the correct case must be identified. To do this, first each special case (<code><span class='Function'>FCase</span></code>, <code><span class='Modifier'>_mCase</span></code>, or <code><span class='Modifier2'>_cCase_</span></code>), excluding <code><span class='Function'>FCase</span></code> nodes containing <code><span class='Function'>UndoHead</span></code>, is checked in order to see if its arguments are strucurally compatible with the given arguments. That is, is <code><span class='Value'>headW</span></code> is a <code><span class='Value'>subject</span></code>, there must be a left argument matching that structure, and if <code><span class='Value'>headX</span></code> is a <code><span class='Value'>subject</span></code>, the right argument must match that structure. This means that <code><span class='Value'>𝕨</span></code> not only matches any left argument but also no argument. The test for compatibility is the same as for multiple assignment described below, except that the header may contain constants, which must match the corresponding part of the given argument. If no special case matches, then an appropriate general case (<code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_mMain</span></code>, or <code><span class='Modifier2'>_cMain_</span></code>) is used: if there are two, the first is used with no left argument and the second with a left argument; if there are one, it is always used, and if there are none, an error results.</p>
<p>The only remaining step before evaluating the <code><span class='Function'>BODY</span></code> is to bind the inputs and other names. Special names are always bound when applicable: <code><span class='Value'>𝕨𝕩𝕀</span></code> if arguments are used, <code><span class='Value'>𝕨</span></code> if there is a left argument, <code><span class='Value'>π•—π•˜</span></code> if operands are used, and <code><span class='Modifier'>_𝕣</span></code> and <code><span class='Modifier2'>_𝕣_</span></code> for modifiers and combinators, respectively. Any names in the header are also bound, allowing multiple assignment for arguments.</p>
<p>If there is no left argument, but the <code><span class='Function'>BODY</span></code> contains <code><span class='Value'>𝕨</span></code> or <code><span class='Function'>π•Ž</span></code> at the top level, then it is conceptually re-parsed with <code><span class='Value'>𝕨</span></code> replaced by <code><span class='Nothing'>Β·</span></code> to give a monadic version before application; this modifies the syntax tree by replacing some instances of <code><span class='Value'>subject</span></code>, <code><span class='Value'>arg</span></code>, or <code><span class='Function'>Operand</span></code> with <code><span class='Value'>nothing</span></code>. The token <code><span class='Function'>π•Ž</span></code> is not allowed in this case and causes an error. Re-parsing <code><span class='Value'>𝕨</span></code> can also cause an error if it's used as an operand or list element, where <code><span class='Value'>nothing</span></code> is not allowed by the grammar. Note that these errors must not appear if the block is always called with two arguments. True re-parsing is not required, as the same effect can also be achieved dynamically by treating <code><span class='Nothing'>Β·</span></code> as a value and checking for it during execution. If it's used as a left argument, then the function should instead be called with no left argument (and similarly in trains); if it's used as a right argument, then the function and its left argument are evaluated but rather than calling the function <code><span class='Nothing'>Β·</span></code> is &quot;returned&quot; immediately; and if it's used in another context then it causes an error.</p>
-<h3 id="assignment">Assignment</h3>
+<h3 id="assignment"><a class="header" href="#assignment">Assignment</a></h3>
<p>An <em>assignment</em> is one of the four rules containing <code><span class='Function'>ASGN</span></code>. It is evaluated by first evaluating the right-hand-side <code><span class='Value'>subExpr</span></code>, <code><span class='Function'>FuncExpr</span></code>, <code><span class='Modifier'>_m1Expr</span></code>, or <code><span class='Modifier2'>_m2Exp_</span></code> expression, and then storing the result in the left-hand-side identifier or identifiers. The result of the assignment expression is the result of its right-hand side. Except for subjects, only a lone identifier is allowed on the left-hand side and storage sets it equal to the result. For subjects, <em>destructuring assignment</em> is performed when an <code><span class='Value'>lhs</span></code> is <code><span class='Value'>lhsList</span></code> or <code><span class='Value'>lhsStr</span></code>. Destructuring assignment is performed recursively by assigning right-hand-side values to the left-hand-side targets, with single-identifier assignment as the base case.</p>
<p>The right-hand-side value, here called <code><span class='Value'>v</span></code>, in destructuring assignment must be a list (rank 1 array) or namespace. If it's a list, then each <code><span class='Function'>LHS_ENTRY</span></code> node must be an <code><span class='Function'>LHS_ELT</span></code>. The left-hand side is treated as a list of <code><span class='Value'>lhs</span></code> targets, and matched to <code><span class='Value'>v</span></code> element-wise, with an error if the two lists differ in length. If <code><span class='Value'>v</span></code> is a namespace, then the left-hand side must be an <code><span class='Value'>lhsStr</span></code> where every <code><span class='Function'>LHS_ATOM</span></code> is an <code><span class='Function'>LHS_NAME</span></code>, or an <code><span class='Value'>lhsList</span></code> where every <code><span class='Function'>LHS_ENTRY</span></code> is an <code><span class='Function'>LHS_NAME</span></code> or <code><span class='Value'>lhs</span> <span class='String'>&quot;⇐&quot;</span> <span class='Function'>LHS_NAME</span></code>, so that it can be considered a list of <code><span class='Function'>LHS_NAME</span></code> nodes some of which are also associated with <code><span class='Value'>lhs</span></code> nodes. To perform the assignment, the value of each name is obtained from the namespace <code><span class='Value'>v</span></code>, giving an error if <code><span class='Value'>v</span></code> does not define that name. The value is assigned to the <code><span class='Value'>lhs</span></code> node if present (which may be a destructuring assignment or simple subject assignment), and otherwise assigned to the same <code><span class='Function'>LHS_NAME</span></code> node used to get it from <code><span class='Value'>v</span></code>.</p>
<p><em>Modified assignment</em> is the subject assignment rule <code><span class='Value'>lhs</span> <span class='Function'>Derv</span> <span class='String'>&quot;↩&quot;</span> <span class='Value'>subExpr</span></code>. In this case, <code><span class='Value'>lhs</span></code> should be evaluated as if it were a <code><span class='Value'>subExpr</span></code> (the syntax is a subset of <code><span class='Value'>subExpr</span></code>), and the result of the function application <code><span class='Value'>lhs</span> <span class='Function'>Derv</span> <span class='Value'>subExpr</span></code> should be assigned to <code><span class='Value'>lhs</span></code>, and is also the result of the modified assignment expression.</p>
-<h3 id="expressions">Expressions</h3>
+<h3 id="expressions"><a class="header" href="#expressions">Expressions</a></h3>
<p>We now give rules for evaluating an <code><span class='Value'>atom</span></code>, <code><span class='Function'>Func</span></code>, <code><span class='Modifier'>_mod1</span></code> or <code><span class='Modifier2'>_mod2_</span></code> expression (the possible options for <code><span class='Function'>ANY</span></code>). A literal or primitive <code><span class='Value'>sl</span></code>, <code><span class='Function'>Fl</span></code>, <code><span class='Modifier'>_ml</span></code>, or <code><span class='Modifier2'>_cl_</span></code> has a fixed value defined by the specification (<a href="literal.html">literals</a> and <a href="primitive.html">built-ins</a>). An identifier <code><span class='Value'>s</span></code>, <code><span class='Function'>F</span></code>, <code><span class='Modifier'>_m</span></code>, or <code><span class='Modifier2'>_c_</span></code>, if not preceded by <code><span class='Value'>atom</span> <span class='String'>&quot;.&quot;</span></code>, must have an associated variable due to the scoping rules, and returns this variable's value, or causes an error if it has not yet been set. If it is preceded by <code><span class='Value'>atom</span> <span class='String'>&quot;.&quot;</span></code>, then the <code><span class='Value'>atom</span></code> node is evaluated first; its value must be a namespace, and the result is the value of the identifier's name in the namespace, or an error if the name is undefined. A parenthesized expression such as <code><span class='String'>&quot;(&quot;</span> <span class='Modifier'>_modExpr</span> <span class='String'>&quot;)&quot;</span></code> simply returns the result of the interior expression. A braced construct such as <code><span class='Function'>BraceFunc</span></code> is defined by the evaluation of the statements it contains after all parameters are accepted. Finally, a list <code><span class='String'>&quot;⟨&quot;</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>(</span> <span class='Paren'>(</span> <span class='Function'>EXPR</span> <span class='Separator'>β‹„</span> <span class='Paren'>)</span><span class='Value'>*</span> <span class='Function'>EXPR</span> <span class='Separator'>β‹„</span><span class='Value'>?</span> <span class='Paren'>)</span><span class='Value'>?</span> <span class='String'>&quot;⟩&quot;</span></code> or <code><span class='Function'>ANY</span> <span class='Paren'>(</span> <span class='String'>&quot;β€Ώ&quot;</span> <span class='Function'>ANY</span> <span class='Paren'>)</span><span class='Function'>+</span></code> consists grammatically of a list of expressions. To evaluate it, each expression is evaluated in source order and their results are placed as elements of a rank-1 array. The two forms have identical semantics but different punctuation.</p>
<p>A <code><span class='Function'>Return</span></code> node creates a return function. As <a href="scope.html#returns">discussed</a> in the scoping rules, its identifier indicates a namespace from a particular block evaluation. When called, the function causes an error if that block has finished execution, or if the call includes a left argument <code><span class='Value'>𝕨</span></code>. Otherwise, evaluation stops immediately, and resumes at the end of the block where it returns the right argument <code><span class='Value'>𝕩</span></code> from that block.</p>
<p>Rules in the table below are function and modifier evaluation.</p>
diff --git a/docs/spec/grammar.html b/docs/spec/grammar.html
index 3ad5bd25..da83d87c 100644
--- a/docs/spec/grammar.html
+++ b/docs/spec/grammar.html
@@ -4,7 +4,7 @@
<title>Specification: BQN grammar</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-grammar">Specification: BQN grammar</h1>
+<h1 id="specification-bqn-grammar"><a class="header" href="#specification-bqn-grammar">Specification: BQN grammar</a></h1>
<p>BQN's grammar is given below. Terms are defined in a <a href="https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form">BNF</a> variant. However, handling special names properly is possible but difficult in BNF, so they are explained in text along with the braced block grammar.</p>
<p>The symbols <code><span class='Value'>s</span></code>, <code><span class='Function'>F</span></code>, <code><span class='Modifier'>_m</span></code>, and <code><span class='Modifier2'>_c_</span></code> are identifier tokens with subject, function, 1-modifier, and 2-modifier classes respectively. Similarly, <code><span class='Value'>sl</span></code>, <code><span class='Function'>Fl</span></code>, <code><span class='Modifier'>_ml</span></code>, and <code><span class='Modifier2'>_cl_</span></code> refer to literals and primitives of those classes. While names in the BNF here follow the identifier naming scheme, this is informative only: syntactic roles are no longer used after parsing and cannot be inspected in a running program.</p>
<p>A program is a list of statements. Almost all statements are expressions. Namespace export statements, and valueless results stemming from <code><span class='Nothing'>Β·</span></code>, or <code><span class='Value'>𝕨</span></code> in a monadic brace function, can be used as statements but not expressions.</p>
diff --git a/docs/spec/index.html b/docs/spec/index.html
index b8f1d80e..fa8ad8c9 100644
--- a/docs/spec/index.html
+++ b/docs/spec/index.html
@@ -4,7 +4,7 @@
<title>BQN specification</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a></div>
-<h1 id="bqn-specification">BQN specification</h1>
+<h1 id="bqn-specification"><a class="header" href="#bqn-specification">BQN specification</a></h1>
<p>This document, and the others in this directory (linked in the list below) make up the pre-versioning BQN specification. The specification differs from the <a href="../doc/index.html">documentation</a> in that its purpose is only to describe the exact details of BQN's operation in the most quickly accessible way, rather than to explain the central ideas of BQN functionality and how it might be used. The core of BQN, which excludes system-provided values, is now almost completely specified. One planned featureβ€”an extension to allow low-rank elements in the argument to Joinβ€”has not yet been added, and the spec will continue to be edited further to improve clarity and cover any edge cases that have been missed.</p>
<p>Under this specification, a language implementation is a <strong>BQN pre-version implementation</strong> if it behaves as specified for all input programs. It is a <strong>BQN pre-version implementation with extensions</strong> if it behaves as specified in all cases where the specification does not require an error, but behaves differently in at least one case where it requires an error. It is a <strong>partial</strong> version of either of these if it doesn't conform to the description but differs from a conforming implementation only by rejecting with an error some programs that the conforming implementation accepts. As the specification is not yet versioned, other instances of the specification define these terms in different ways. An implementation can use one of these terms if it conforms to any instance of the pre-versioning BQN specifications that defines them. When versioning is begun, there will be only one specification for each version.</p>
<p>The following documents are included in the BQN specification. A BQN program is a sequence of <a href="https://en.wikipedia.org/wiki/Unicode">Unicode</a> code points: to evaluate it, it is converted into a sequence of tokens using the token formation rules, then these tokens are arranged in a syntax tree according to the grammar, and then this tree is evaluated according to the evaluation semantics. The program may be evaluated in the presence of additional context such as a filesystem or command-line arguments; this context is presented to the program and manipulated through the system-provided values.</p>
diff --git a/docs/spec/inferred.html b/docs/spec/inferred.html
index c25ad29c..c0deb923 100644
--- a/docs/spec/inferred.html
+++ b/docs/spec/inferred.html
@@ -4,11 +4,11 @@
<title>Specification: BQN inferred properties</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-inferred-properties">Specification: BQN inferred properties</h1>
+<h1 id="specification-bqn-inferred-properties"><a class="header" href="#specification-bqn-inferred-properties">Specification: BQN inferred properties</a></h1>
<p>BQN includes some simple deductive capabilities: detecting the type of empty array elements, the result of an empty reduction, and the Undo (<code><span class='Modifier'>⁼</span></code>) and Under (<code><span class='Modifier2'>⌾</span></code>) modifiers. These tasks are a kind of proof-based or constraint programming, and can never be solved completely (some instances will be undecidable) but can be solved in more instances by ever-more sophisticated algorithms. To allow implementers to develop more advanced implementations while offering some stability and portability to programmers, two kinds of specification are given here. First, constraints are given on the behavior of inferred properties. These are not exact and require some judgment on the part of the implementer. Second, behavior for common or useful cases is specified more precisely. Non-normative suggestions are also given as a reference for implementers.</p>
<p>For the specified cases, the given functions and modifiers refer to those particular representations. It is not necessary to detect equivalent representations, for example to reduce <code><span class='Paren'>(</span><span class='Function'>+-Γ—</span><span class='Paren'>)</span><span class='Modifier'>⁼</span></code> to <code><span class='Function'>∨</span><span class='Modifier'>⁼</span></code>. However, it is necessary to identify computed functions and modifiers: for example <code><span class='Function'>F</span><span class='Modifier'>⁼</span></code> when the value of <code><span class='Function'>F</span></code> in the expression is <code><span class='Function'>∨</span></code>, or <code><span class='Paren'>(</span><span class='Number'>1</span><span class='Function'>βŠ‘βˆ§</span><span class='Ligature'>β€Ώ</span><span class='Function'>∨</span><span class='Paren'>)</span><span class='Modifier'>⁼</span></code>.</p>
<p>Failing to compute an inferred property for a function or array as it's created cannot cause an error. An error can only be caused when the missing inferred property is needed for a computation.</p>
-<h2 id="identities">Identities</h2>
+<h2 id="identities"><a class="header" href="#identities">Identities</a></h2>
<p>When monadic Fold (<code><span class='Modifier'>Β΄</span></code>) or Insert (<code><span class='Modifier'>˝</span></code>) is called on an array of length 0, BQN attempts to infer a right identity value for the function in order to determine the result. A right identity value for a dyadic function <code><span class='Function'>𝔽</span></code> is a value <code><span class='Value'>r</span></code> such that <code><span class='Value'>e</span><span class='Function'>≑</span><span class='Value'>e</span><span class='Function'>𝔽</span><span class='Value'>r</span></code> for any element <code><span class='Value'>e</span></code> in the domain. For such a value <code><span class='Value'>r</span></code>, the fold <code><span class='Value'>r</span> <span class='Function'>𝔽</span><span class='Modifier'>Β΄</span> <span class='Value'>l</span></code> is equivalent to <code><span class='Function'>𝔽</span><span class='Modifier'>Β΄</span> <span class='Value'>l</span></code> for a non-empty list <code><span class='Value'>l</span></code>, because the first application <code><span class='Paren'>(</span><span class='Number'>Β―1</span><span class='Function'>βŠ‘</span><span class='Value'>l</span><span class='Paren'>)</span> <span class='Function'>𝔽</span> <span class='Value'>r</span></code> gives <code><span class='Number'>Β―1</span><span class='Function'>βŠ‘</span><span class='Value'>l</span></code>, which is the starting point when no initial value is given. It's thus reasonable to define <code><span class='Function'>𝔽</span><span class='Modifier'>Β΄</span> <span class='Value'>l</span></code> to be <code><span class='Value'>r</span> <span class='Function'>𝔽</span><span class='Modifier'>Β΄</span> <span class='Value'>l</span></code> for an empty list <code><span class='Value'>l</span></code> as well, giving a result <code><span class='Value'>r</span></code>.</p>
<p>For Fold, the result of <code><span class='Function'>𝔽</span><span class='Modifier'>Β΄</span></code> on an empty list is defined to be a right identity value for the <em>range</em> of <code><span class='Function'>𝔽</span></code>, if exactly one such value exists. If an identity can't be proven to uniquely exist, then an error results.</p>
<p>For Insert, <code><span class='Function'>𝔽</span><span class='Modifier'>˝</span></code> on an array of length 0 is defined similarly, but also depends on the cell shape <code><span class='Number'>1</span><span class='Function'>↓≒</span><span class='Value'>𝕩</span></code>. The required domain is the arrays of that shape that also lie in the range of <code><span class='Function'>𝔽</span></code> (over arbitrary arguments, not shape-restricted ones). Furthermore, an identity may be unique among all possible arguments as in the case of Fold, or it may be an array with shape <code><span class='Number'>1</span><span class='Function'>↓≒</span><span class='Value'>𝕩</span></code> and be unique among arrays with that shape. For example, with cell shape <code><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span></code>, all of <code><span class='Number'>0</span></code>, <code><span class='Number'>2</span><span class='Function'>β₯Š</span><span class='Number'>0</span></code>, and <code><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span><span class='Function'>β₯Š</span><span class='Number'>0</span></code> are identities for <code><span class='Function'>+</span></code>, but <code><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span><span class='Function'>β₯Š</span><span class='Number'>0</span></code> can be used because it is the only indentity with shape <code><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>2</span></code>, while the other identities aren't unique and can't be used.</p>
@@ -68,11 +68,11 @@
</tbody>
</table>
<p>Additionally, the identity of <code><span class='Function'>∾</span><span class='Modifier'>˝</span></code> must be recognized: if <code><span class='Number'>0</span><span class='Function'>=β‰ </span><span class='Value'>𝕩</span></code> and <code><span class='Number'>1</span><span class='Function'>&lt;=</span><span class='Value'>𝕩</span></code>, then <code><span class='Function'>∾</span><span class='Modifier'>˝</span><span class='Value'>𝕩</span></code> is <code><span class='Paren'>(</span><span class='Number'>0</span><span class='Function'>∾</span><span class='Number'>2</span><span class='Function'>↓≒</span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>β₯Š</span><span class='Value'>𝕩</span></code>. If <code><span class='Number'>1</span><span class='Function'>==</span><span class='Value'>𝕩</span></code>, then there is no identity element, as the result of <code><span class='Function'>∾</span></code> always has rank at least 1, but the cell rank is 0.</p>
-<h2 id="fill-elements">Fill elements</h2>
+<h2 id="fill-elements"><a class="header" href="#fill-elements">Fill elements</a></h2>
<p>Any BQN array can have a <em>fill element</em>, which is a sort of &quot;default&quot; value for the array. The reference implementations use <code><span class='Function'>Fill</span></code> to access this element, and it is used primarily for Take (<code><span class='Function'>↑</span></code>), First (<code><span class='Function'>βŠ‘</span></code>), and Nudge (<code><span class='Function'>Β«</span></code>, <code><span class='Function'>Β»</span></code>). One way to extract the fill element of an array <code><span class='Value'>a</span></code> in BQN is <code><span class='Function'>βŠ‘</span><span class='Number'>0</span><span class='Function'>β₯Š</span><span class='Value'>a</span></code>.</p>
<p>A fill element can be either <code><span class='Number'>0</span></code>, <code><span class='String'>' '</span></code>, or an array of valid fill elements. If the fill element is an array, then it may also have a fill element (since it is an ordinary BQN array). The fill element is meant to describe the shared structure of the elements of an array: for example, the fill element of an array of numbers should be <code><span class='Number'>0</span></code>, while the fill element for an array of variable-length lists should probably be <code><span class='Bracket'>⟨⟩</span></code>. However, the fill element, unlike other inferred properties, does not satisfy any particular constraints that relate it to its array. The fill element of a primitive's result, including functions derived from primitive modifiers, must depend only on its inputs.</p>
<p>In addition to the requirements below, the fill element for the value of a string literal is <code><span class='String'>' '</span></code>.</p>
-<h3 id="required-functions">Required functions</h3>
+<h3 id="required-functions"><a class="header" href="#required-functions">Required functions</a></h3>
<p>Combinators <code><span class='Function'>⊣⊒!</span><span class='Modifier'>Λ™ΛœΒ΄Λ</span><span class='Modifier2'>βˆ˜β—‹βŠΈβŸœβŠ˜β—ΆβŸ</span></code> do not affect fill element computation: if the combinator calls a function that computes a fill element, then that fill element must be retained if the result is passed to other functions or returned. <code><span class='Modifier2'>⍟</span></code> constructs arrays if its right operand is or contains arrays, and the fill elements of these arrays are not specified; converting <code><span class='Value'>𝕩</span></code> to a fill element is a reasonable choice in some cases but not others.</p>
<p>Arithmetic primitivesβ€”all valences of <code><span class='Function'>+-Γ—Γ·β‹†βˆšβŒŠβŒˆ|Β¬</span></code> and dyadic <code><span class='Function'>∧∨&lt;&gt;β‰ =≀β‰₯</span></code>β€”obtain their fill elements by applying to the fill elements of the arguments. If this is an error, there is no fill element; otherwise, the fill element is the result, with all numbers in it changed to <code><span class='Number'>0</span></code> and all characters changed to <code><span class='String'>' '</span></code>.</p>
<p>Fill elements for many primitives are given in the table below. The &quot;Fill&quot; column indicates the strategy used to compute the result's fill. Fields <code><span class='Number'>0</span></code>, <code><span class='Value'>𝕩</span></code>, <code><span class='Number'>0</span><span class='Function'>↑</span><span class='Value'>𝕩</span></code>, and <code><span class='Number'>0</span><span class='Modifier2'>βš‡</span><span class='Number'>0</span><span class='Value'>𝕩</span></code> indicate the fill directly, while <code><span class='Function'>⊒</span></code> and <code><span class='Value'>∩</span></code> indicate that the fill is to be computed from the argument fills (if not all arguments have fills, then the fill element is unspecified). For <code><span class='Function'>⊒</span></code>, the fill element of the result is the fill element of <code><span class='Value'>𝕩</span></code>. For <code><span class='Value'>∩</span></code>, the fill is equal to the fill values for multiple arrays, provided that they are all equal (it's unspecified if they are not all equal). In the two argument case, these arrays are <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code>. In the one-argument case, they are the elements of <code><span class='Value'>𝕩</span></code>; however, if <code><span class='Value'>𝕩</span></code> is empty, then the result's fill is the fill of the fill of <code><span class='Value'>𝕩</span></code>.</p>
@@ -120,11 +120,11 @@
</table>
<p>For Group and Group Indices (<code><span class='Function'>βŠ”</span></code>), the fill element of the result and its elements are both specified: the fill element of each element of the result is the same as that of <code><span class='Value'>𝕩</span></code> for Group, and is <code><span class='Number'>0</span></code> for Group Indices. The fill element of the result is <code><span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βš‡</span><span class='Number'>1</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>↑</span><span class='Value'>𝕩</span></code> for Group, and <code><span class='Function'>β₯Š</span><span class='Modifier2'>⟜</span><span class='Function'>&lt;</span><span class='Number'>0</span><span class='Modifier2'>βš‡</span><span class='Number'>1</span><span class='Value'>𝕩</span></code> for Group Indices.</p>
<p>Fill elements of iteration modifiers such as <code><span class='Modifier'>¨⌜</span></code> are not specified. It is reasonable to define the fill element of <code><span class='Function'>𝔽</span><span class='Modifier'>⌜</span></code> or <code><span class='Function'>𝔽</span><span class='Modifier'>Β¨</span></code> to be <code><span class='Function'>𝔽</span></code> applied to the fill elements of the arguments. Regardless of definition, computing the fill element cannot cause side effects or an error.</p>
-<h2 id="undo">Undo</h2>
+<h2 id="undo"><a class="header" href="#undo">Undo</a></h2>
<p>The Undo 1-modifier <code><span class='Modifier'>⁼</span></code>, given an operand <code><span class='Function'>𝔽</span></code> and argument <code><span class='Value'>𝕩</span></code>, and possibly a left argument <code><span class='Value'>𝕨</span></code>, finds a value <code><span class='Value'>y</span></code> such that <code><span class='Value'>𝕩</span><span class='Function'>≑</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Value'>y</span></code>, that is, an element of the pre-image of <code><span class='Value'>𝕩</span></code> under <code><span class='Function'>𝔽</span></code> or <code><span class='Value'>𝕨</span><span class='Function'>π”½βŠ’</span></code>. Thus it satisfies the constraint <code><span class='Value'>𝕩</span> <span class='Function'>≑</span> <span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier'>⁼</span><span class='Value'>𝕩</span></code> (<code><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier'>⁼</span><span class='Function'>⊒</span></code> is a <em>right inverse</em> of <code><span class='Value'>𝕨</span><span class='Function'>π”½βŠ’</span></code>) provided <code><span class='Function'>𝔽</span><span class='Modifier'>⁼</span></code> and <code><span class='Function'>𝔽</span></code> both complete without error. <code><span class='Function'>𝔽</span><span class='Modifier'>⁼</span></code> should of course give an error if no inverse element exists, and can also fail if no inverse can be found. It is also preferred for <code><span class='Function'>𝔽</span><span class='Modifier'>⁼</span></code> to give an error if there are many choices of inverse with no clear way to choose one of them: for example, <code><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Function'>⍉</span><span class='Value'>m</span></code> returns the diagonal of matrix <code><span class='Value'>m</span></code>; <code><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Function'>⍉</span><span class='Modifier'>⁼</span><span class='Number'>2</span><span class='Ligature'>β€Ώ</span><span class='Number'>3</span></code> requires values to be chosen for the off-diagonal elements in its result. It is better to give an error, encouraging the programmer to use a fully-specified approach like <code><span class='Number'>2</span><span class='Ligature'>β€Ώ</span><span class='Number'>3</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Modifier2'>⊸</span><span class='Function'>⍉</span><span class='Paren'>)</span></code> applied to a matrix of initial elements, than to return a result that could be very different from other implementations.</p>
<p>When working with limited-precision numbers, it may be difficult or impossible to exactly invert the operand function. Instead, it is generally acceptable to perform a computation that, if done with unlimited precision, would exactly invert <code><span class='Function'>𝔽</span></code> computed with unlimited precision. This principle is the basis for the numeric inverses specified below. It is also acceptable to find an inverse by numeric methods, provided that the error in the inverse value found relative to an unlimited-precision inverse can be kept close to the inherent error in the implementation's number format.</p>
<p>Regardless of which cases for Undo are supported, the result of a call, and whether it is an error, must depend only on the values of the inputs <code><span class='Function'>𝔽</span></code>, <code><span class='Value'>𝕩</span></code>, and (if present) <code><span class='Value'>𝕨</span></code>.</p>
-<h3 id="required-functions">Required functions</h3>
+<h3 id="required-functions"><a class="header" href="#required-functions">Required functions</a></h3>
<p>Function inverses are given for one or two arguments, with cases where inverse support is not required left blank.</p>
<p>For arithmetic functions the implementations below may in some cases not give the closest inverse (that is, there may be some other <code><span class='Value'>y</span></code> so that <code><span class='Function'>F</span> <span class='Value'>y</span></code> is closer to <code><span class='Value'>x</span></code> than <code><span class='Function'>F</span> <span class='Function'>F</span><span class='Modifier'>⁼</span><span class='Value'>x</span></code>). Even in these cases the exact functions given below must be used.</p>
<table>
@@ -247,7 +247,7 @@
</tr>
</tbody>
</table>
-<h3 id="optional-functions">Optional functions</h3>
+<h3 id="optional-functions"><a class="header" href="#optional-functions">Optional functions</a></h3>
<p>Several primitives are easily and uniquely undone, but doing so is not important for BQN programming. These primitives are listed below along with suggested algorithms to undo them. Unlike the implementations above, these functions are not valid in all cases, and the inputs must be validated or the results checked in order to use them.</p>
<table>
<thead>
@@ -300,7 +300,7 @@
</tr>
</tbody>
</table>
-<h3 id="required-modifiers">Required modifiers</h3>
+<h3 id="required-modifiers"><a class="header" href="#required-modifiers">Required modifiers</a></h3>
<p>The following cases of Self/Swap must be supported.</p>
<table>
<thead>
@@ -464,9 +464,9 @@
</tr>
</tbody>
</table>
-<h3 id="undo-headers">Undo headers</h3>
+<h3 id="undo-headers"><a class="header" href="#undo-headers">Undo headers</a></h3>
<p>An <code><span class='Function'>UndoHead</span></code> header specifies how a block function acts when undone. Like ordinary headers, undo headers are searched for a match when a block function <code><span class='Function'>F</span></code> is undone, or when <code><span class='Function'>F</span><span class='Modifier'>˜</span></code> is undone with two arguments (including the two modifier cases <code><span class='Function'>𝔽</span><span class='Modifier2'>⟜</span><span class='Value'>k</span></code> and <code><span class='Function'>𝔽𝔾</span><span class='Value'>k</span></code> from the previous section). An <code><span class='Function'>UndoHead</span></code> without <code><span class='String'>&quot;˜&quot;</span></code> matches the <code><span class='Function'>F</span><span class='Modifier'>⁼</span></code> case while one with <code><span class='String'>&quot;˜&quot;</span></code> matches the <code><span class='Function'>F</span><span class='Modifier'>˜⁼</span></code> case. The left and right arguments are matched to <code><span class='Value'>headW</span></code> and <code><span class='Value'>headX</span></code> as with ordinary headers, and the first matching case is evaluated to give the result of the Undo-derived function.</p>
-<h2 id="under">Under</h2>
+<h2 id="under"><a class="header" href="#under">Under</a></h2>
<p>The Under 2-modifier <code><span class='Modifier2'>⌾</span></code> conceptually applies its left operand under the action of its right operand. Setting <code><span class='Value'>z</span><span class='Gets'>←</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier2'>⌾</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span></code>, it satisfies <code><span class='Paren'>(</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier2'>β—‹</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span><span class='Paren'>)</span> <span class='Function'>≑</span> <span class='Function'>𝔾</span><span class='Value'>z</span></code>. We might say that <code><span class='Function'>𝔾</span></code> transforms values to a new domain, and <code><span class='Modifier2'>⌾</span><span class='Function'>𝔾</span></code> lifts actions <code><span class='Function'>𝔽</span></code> performed in this domain to the original domain of values. For example, addition in the logarithmic domain corresponds to multiplication in the linear domain: <code><span class='Function'>+</span><span class='Modifier2'>⌾</span><span class='Paren'>(</span><span class='Function'>⋆</span><span class='Modifier'>⁼</span><span class='Paren'>)</span></code> is <code><span class='Function'>Γ—</span></code> (but less precise if computed in floating point).</p>
<p>Let <code><span class='Value'>v</span><span class='Gets'>←</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier2'>β—‹</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span></code>, so that <code><span class='Value'>v</span><span class='Function'>≑𝔾</span><span class='Value'>z</span></code>. <code><span class='Value'>v</span></code> is of course well-defined, so the inference step is to find <code><span class='Value'>z</span></code> based on <code><span class='Value'>v</span></code> and possibly the original inputs. We distinguish three cases for Under:</p>
<ul>
@@ -475,7 +475,7 @@
<li><em>Computational</em> Under: If <code><span class='Function'>𝔾</span></code> is provably not a structural function, then the result is <code><span class='Function'>𝔾</span><span class='Modifier'>⁼</span><span class='Value'>v</span></code> if it is defined.</li>
</ul>
<p>When implementing, there is no need to implement invertable Under specially: it can be handled as part of the structural and computation cases.</p>
-<h3 id="mathematical-definition-of-structural-under">Mathematical definition of structural Under</h3>
+<h3 id="mathematical-definition-of-structural-under"><a class="header" href="#mathematical-definition-of-structural-under">Mathematical definition of structural Under</a></h3>
<p>In general, structural Under requires information from the original right argument to be computed. Here we will define the <em>structural inverse of</em> structural function <code><span class='Function'>𝔾</span></code> <em>on</em> <code><span class='Value'>v</span></code> <em>into</em> <code><span class='Value'>𝕩</span></code>, where <code><span class='Value'>𝕩</span></code> gives this information. The value <code><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier2'>⌾</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span></code> is then the structural inverse of <code><span class='Function'>𝔾</span></code> on <code><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier2'>β—‹</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span></code> into <code><span class='Value'>𝕩</span></code>.</p>
<p>We define a <em>structure</em> to be either the value <code><span class='Nothing'>Β·</span></code> or an array of structures (substitute <code><span class='Number'>0</span></code> or any other specific value for <code><span class='Nothing'>Β·</span></code> if you'd like structures to be a subset of BQN arrays; the value is irrelevant). A given structure <code><span class='Value'>s</span></code> <em>captures</em> a BQN value or structure <code><span class='Value'>𝕩</span></code> if it is <code><span class='Nothing'>Β·</span></code>, or if <code><span class='Value'>s</span></code> and <code><span class='Value'>𝕩</span></code> are arrays of the same shape, and each element of <code><span class='Value'>s</span></code> captures the corresponding element of <code><span class='Value'>𝕩</span></code>. Thus a structure shares some or all of the structural information in arrays it captures, but none of the data.</p>
<p>A <em>structure transformation</em> consists of an initial structure <code><span class='Value'>s</span></code> and a result structure <code><span class='Value'>t</span></code>, as well as a relation between the two: each instance of <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>t</span></code> is assigned the location of an instance of <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>s</span></code>. If <code><span class='Value'>s</span></code> captures a value <code><span class='Value'>𝕩</span></code>, we say that the structural transformation captures <code><span class='Value'>𝕩</span></code> as well. Given such a value <code><span class='Value'>𝕩</span></code>, the transformation is applied to <code><span class='Value'>𝕩</span></code> by replacing each <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>t</span></code> with the corresponding value from <code><span class='Value'>𝕩</span></code>, found by taking the same location in <code><span class='Value'>𝕩</span></code> as the one in <code><span class='Value'>s</span></code> given by the transformation.</p>
@@ -488,10 +488,10 @@
<p>Following this analysis, <code><span class='Value'>z</span></code> can be constructed by replacing each instance of <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>s</span></code> with the component of <code><span class='Value'>𝕩</span></code> or <code><span class='Value'>v</span></code> indicated, and it follows that <code><span class='Value'>z</span></code> is well-defined if it existsβ€”and it exists if and only if <code><span class='Value'>t</span></code> captures <code><span class='Value'>v</span></code> and values in <code><span class='Value'>v</span></code> that correspond to the same position in <code><span class='Value'>s</span></code> have the same value.</p>
<p>A <em>structural function decomposition</em> is a possibly infinite family of structure transformations such that any possible BQN value is captured by at most one of these transformations. It can be applied to any value: if some transformation captures the value, then apply that transformation, and otherwise give an error. A function is a <em>structural function</em> if there is a structural function decomposition that matches it: that is, for any input either both functions give an error or the results match.</p>
<p>For a structural function <code><span class='Function'>𝔾</span></code>, the <em>structural inverse</em> of <code><span class='Function'>𝔾</span></code> on <code><span class='Value'>v</span></code> into <code><span class='Value'>𝕩</span></code> is the inverse of <code><span class='Function'>G</span></code> on <code><span class='Value'>v</span></code> into <code><span class='Value'>𝕩</span></code>, where <code><span class='Function'>G</span></code> is the structure transformation that captures <code><span class='Value'>𝕩</span></code> from some structural function decomposition <code><span class='Function'>Gd</span></code> matching <code><span class='Function'>𝔾</span></code>. If no decomposition has an initial structural matching <code><span class='Value'>𝕩</span></code> then the structural inverse does not exist.</p>
-<h4 id="well-definedness">Well-definedness</h4>
+<h4 id="well-definedness"><a class="header" href="#well-definedness">Well-definedness</a></h4>
<p>In order to show that the structural inverse of a structural function is well-defined, we must show that it does not depend on the choice of structural function decomposition. That is, for a given <code><span class='Value'>𝕩</span></code>, if <code><span class='Function'>G</span></code> and <code><span class='Function'>H</span></code> are structure transformations from different decompositions of <code><span class='Function'>𝔾</span></code> both capturing <code><span class='Value'>𝕩</span></code>, then the structural inverse of <code><span class='Function'>G</span></code> on <code><span class='Value'>v</span></code> into <code><span class='Value'>𝕩</span></code> matches that of <code><span class='Function'>H</span></code> on <code><span class='Value'>v</span></code> into <code><span class='Value'>𝕩</span></code>. Call these inverses <code><span class='Value'>y</span></code> and <code><span class='Value'>z</span></code>. Now begin by supposing that <code><span class='Function'>H</span></code> captures <code><span class='Value'>y</span></code> and <code><span class='Function'>G</span></code> captures <code><span class='Value'>z</span></code>; we will show this later. From the definition of a structural inverse, <code><span class='Value'>v</span><span class='Function'>≑G</span> <span class='Value'>y</span></code>, so that <code><span class='Value'>v</span><span class='Function'>≑𝔾</span> <span class='Value'>y</span></code>, and because <code><span class='Function'>H</span></code> captures <code><span class='Value'>y</span></code> we know that <code><span class='Function'>𝔾</span> <span class='Value'>y</span></code> is <code><span class='Function'>H</span> <span class='Value'>y</span></code>, so we have <code><span class='Value'>v</span><span class='Function'>≑H</span> <span class='Value'>y</span></code> as well. Let <code><span class='Function'>S</span> <span class='Value'>w</span></code> indicate the set of all structure transformations <code><span class='Function'>F</span></code> such that <code><span class='Value'>w</span> <span class='Function'>≑</span><span class='Modifier2'>β—‹</span><span class='Function'>F</span> <span class='Value'>𝕩</span></code> (this is not a BQN value, both because it is a set and because it's usually infinite): from the definition of <code><span class='Value'>z</span></code> we know that <code><span class='Function'>S</span> <span class='Value'>z</span></code> is a strict superset of <code><span class='Function'>S</span> <span class='Value'>w</span></code> for any <code><span class='Value'>w</span></code> other than <code><span class='Value'>z</span></code> with <code><span class='Value'>v</span><span class='Function'>≑H</span> <span class='Value'>w</span></code>. It follows that either <code><span class='Value'>y</span><span class='Function'>≑</span><span class='Value'>z</span></code> or <code><span class='Function'>S</span> <span class='Value'>y</span></code> is a strict subset of <code><span class='Function'>S</span> <span class='Value'>z</span></code>. By symmetry the same relation holds exchanging <code><span class='Value'>y</span></code> and <code><span class='Value'>z</span></code>, but it's not possible for <code><span class='Function'>S</span> <span class='Value'>y</span></code> to be a strict subset of <code><span class='Function'>S</span> <span class='Value'>z</span></code> and vice-versa. The only remaining possibility is that <code><span class='Value'>y</span><span class='Function'>≑</span><span class='Value'>z</span></code>.</p>
<p>We now need to show that <code><span class='Function'>H</span></code> captures <code><span class='Value'>y</span></code> (the proof that <code><span class='Function'>G</span></code> captures <code><span class='Value'>z</span></code> is of course the same as <code><span class='Function'>H</span></code> and <code><span class='Function'>G</span></code> are symmetric). To do this we must show that any array in the initial structure of <code><span class='Function'>H</span></code> corresponds to a matching array in <code><span class='Value'>y</span></code>. For convenience, we will call the initial structures of the two transformations <code><span class='Value'>iG</span></code> and <code><span class='Value'>iH</span></code>, and the final structures <code><span class='Value'>fG</span></code> and <code><span class='Value'>fH</span></code>, and use the notation <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>a</span></code> to indicate the value of array <code><span class='Value'>a</span></code> at position <code><span class='Value'>p</span></code>. Choose the position of an array in <code><span class='Function'>H</span></code>, and assume by induction that each array containing it already has the desired property; this implies that this position exists in <code><span class='Value'>y</span></code> as well although we know nothing about its contents. <code><span class='Function'>G</span></code> captures <code><span class='Value'>y</span></code>, so <code><span class='Value'>iG</span></code> is <code><span class='Nothing'>Β·</span></code> at this position or some parent position; call this position in <code><span class='Value'>iG</span></code> <code><span class='Value'>p</span></code>. There are now two cases: either <code><span class='Function'>G</span></code> makes use of this <code><span class='Value'>p</span></code>β€”at least one position in <code><span class='Value'>fG</span></code> corresponds to itβ€”or it doesn't. If it doesn't, then the contents of <code><span class='Value'>y</span></code> at <code><span class='Value'>p</span></code> are the same as those of <code><span class='Value'>𝕩</span></code>. Since <code><span class='Function'>H</span></code> captures <code><span class='Value'>𝕩</span></code>, <code><span class='Value'>iH</span></code> matches <code><span class='Value'>𝕩</span></code> and hence <code><span class='Value'>y</span></code> as well at <code><span class='Value'>p</span></code>. If it does, then let <code><span class='Value'>s</span></code> be a position in <code><span class='Value'>fG</span></code> that corresponds to <code><span class='Value'>p</span></code> (if there are multiple possibilities, choose one). From <code><span class='Value'>v</span><span class='Function'>≑G</span> <span class='Value'>y</span></code>, we know that <code><span class='Value'>s</span><span class='Function'>βŠ‘</span><span class='Value'>v</span></code> matches <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>y</span></code>. We know that <code><span class='Value'>fH</span></code> captures <code><span class='Value'>v</span></code>, so that <code><span class='Value'>s</span><span class='Function'>βŠ‘</span><span class='Value'>fH</span></code> captures <code><span class='Value'>s</span><span class='Function'>βŠ‘</span><span class='Value'>v</span></code>, or <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>y</span></code>. But we can show that the value of <code><span class='Value'>s</span><span class='Function'>βŠ‘</span><span class='Value'>fH</span></code> is the same as <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>iH</span></code>, which would prove that <code><span class='Function'>H</span></code> captures <code><span class='Value'>y</span></code> at <code><span class='Value'>p</span></code>. To show this, construct an array <code><span class='Value'>xp</span></code> by replacing the value of <code><span class='Value'>𝕩</span></code> at <code><span class='Value'>p</span></code> with <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>iH</span></code> (to be more careful in our handling of types, we might replace every <code><span class='Nothing'>Β·</span></code> with some value that never appears in <code><span class='Value'>𝕩</span></code>). Both <code><span class='Function'>H</span></code> and <code><span class='Function'>G</span></code> capture <code><span class='Value'>xp</span></code>: clearly they capture it outside <code><span class='Value'>p</span></code>, while at <code><span class='Value'>p</span></code> itself, <code><span class='Value'>iG</span></code> is <code><span class='Nothing'>Β·</span></code> and <code><span class='Value'>iH</span></code> is equal to <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>xp</span></code>. Now <code><span class='Paren'>(</span><span class='Function'>H</span> <span class='Value'>xp</span><span class='Paren'>)</span><span class='Function'>≑</span><span class='Paren'>(</span><span class='Function'>G</span> <span class='Value'>xp</span><span class='Paren'>)</span></code> because both functions match <code><span class='Function'>𝔾</span></code> on their domains. Therefore <code><span class='Value'>s</span><span class='Function'>βŠ‘H</span> <span class='Value'>xp</span></code> matches <code><span class='Value'>s</span><span class='Function'>βŠ‘G</span> <span class='Value'>xp</span></code>, which by the definition of <code><span class='Value'>s</span></code> matches <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>xp</span></code>, which matches <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>iH</span></code>. But <code><span class='Value'>s</span><span class='Function'>βŠ‘H</span> <span class='Value'>xp</span></code> comes from replacing each atom in <code><span class='Value'>s</span><span class='Function'>βŠ‘</span><span class='Value'>fH</span></code> with an atom in <code><span class='Value'>xp</span></code> that's captured by a <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>iH</span></code>. Because it matches <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>iH</span></code>, every atom in <code><span class='Value'>s</span><span class='Function'>βŠ‘H</span> <span class='Value'>xp</span></code> is <code><span class='Nothing'>Β·</span></code>, but the only instances of <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>xp</span></code> come from our inserted copy of <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>iH</span></code> and each is immediately captured by the corresponding <code><span class='Nothing'>Β·</span></code> in <code><span class='Value'>iH</span></code>. It follows that <code><span class='Value'>s</span><span class='Function'>βŠ‘H</span> <span class='Value'>xp</span></code>, and consequently <code><span class='Value'>s</span><span class='Function'>βŠ‘</span><span class='Value'>fH</span></code>, is exactly <code><span class='Value'>p</span><span class='Function'>βŠ‘</span><span class='Value'>iH</span></code>, completing the proof.</p>
-<h3 id="required-structural-inverses">Required structural inverses</h3>
+<h3 id="required-structural-inverses"><a class="header" href="#required-structural-inverses">Required structural inverses</a></h3>
<p>The following primitive functions be fully supported by structural Under. Each manipulates its right argument structurally.</p>
<table>
<thead>
@@ -570,7 +570,7 @@
</tr>
</tbody>
</table>
-<h3 id="a-structural-under-algorithm">A structural Under algorithm</h3>
+<h3 id="a-structural-under-algorithm"><a class="header" href="#a-structural-under-algorithm">A structural Under algorithm</a></h3>
<p>This section offers the outline for a procedure that computes most structural inverses that a programmer would typically use. The concept is to build a special result array whose elements are not BQN values but instead indicate positions within the initial argument. This structural array is applied to the initial argument by replacing its elements with the values at those positions, and inverted by placing elements back in the original array at these indices, checking for any conflicts. If operations like dyadic <code><span class='Function'>∾</span></code> are allowed, then a structural array might have some indices that are prefixes or parents of others, making it slightly different from a structural transformation as defined above (although it could be represented as a structural transformation by expanding some of these). This requires additional checking to ensure that elements of previously inserted elements can't be modified.</p>
<p>Structural functions can be applied to structural arrays directly, after ensuring that they have the necessary depth as given below. An array's depth can be increased by expanding each position in it into an array of child positions, or, if that position contains an atom and the structural function in question would tolerate an atom, enclosing it.</p>
<table>
@@ -610,7 +610,7 @@
</tbody>
</table>
<p>Not all primitives in the table above are required. Of note are <code><span class='Function'>=β‰ β‰’</span></code>, which accept a structural array but return an ordinary value; this might be used as a left argument later. If the final result is not structural, then the function in question can't be structural, and the attempt to find a structural inverse can be aborted.</p>
-<h3 id="non-structural-case">Non-structural case</h3>
+<h3 id="non-structural-case"><a class="header" href="#non-structural-case">Non-structural case</a></h3>
<p>The behavior of invertible and computational Under is fully dependent on that of <a href="#undo">Undo</a>, and does not need to be repeated here. However, it is important to discuss when this definition can be applied: specifically, either</p>
<ul>
<li>When <code><span class='Function'>𝔾</span></code> is exactly invertible, or</li>
diff --git a/docs/spec/literal.html b/docs/spec/literal.html
index 3b2b248a..35a280cc 100644
--- a/docs/spec/literal.html
+++ b/docs/spec/literal.html
@@ -4,7 +4,7 @@
<title>Specification: BQN literal notation</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-literal-notation">Specification: BQN literal notation</h1>
+<h1 id="specification-bqn-literal-notation"><a class="header" href="#specification-bqn-literal-notation">Specification: BQN literal notation</a></h1>
<p>A <em>literal</em> is a single <a href="token.html">token</a> that indicates a fixed character, number, or array. While literals indicate values of a data type, <a href="primitive.html">primitives</a> indicate values of an operation type: function, 1-modifier, or 2-modifier.</p>
<p>Two types of literal deal with text. As the source code is considered to be a sequence of unicode code points (&quot;characters&quot;), and these code points are also used for BQN's character <a href="types.html">data type</a>, the representation of a text literal is very similar to its value. In a text literal, the newline character is always represented using the ASCII line feed character, code point 10. A <em>character literal</em> is enclosed with single quotes <code><span class='String'>'</span></code> and its value is identical to the single character between them. A <em>string literal</em> is enclosed in double quotes <code><span class='String'>&quot;</span></code>, and any double quotes between them must come in pairs, as a lone double quote marks the end of the literal. The value of a string literal is a rank-1 array whose elements are the characters in between the enclosing quotes, after replacing each pair of double quotes with only one such quote. The <em>null literal</em> is the token <code><span class='String'>@</span></code> and represents the null character, code point 0.</p>
<p>The format of a <em>numeric literal</em> is more complicated. From the <a href="token.html">tokenization rules</a>, a numeric literal consists of a numeric character (one of <code><span class='Number'>Β―βˆžΟ€.0123456789</span></code>) followed by any number of numeric or alphabetic characters. Some numeric literals are <em>valid</em> and indicate a number, while others are invalid and cause an error. The grammar for valid numbers is given below in a <a href="https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form">BNF</a> variant. Only four alphabetic characters are allowed: &quot;i&quot;, which separates the real and imaginary components of a complex number, &quot;e&quot;, which functions as in scientific notation, and the uppercase versions of these letters. Not included in this grammar are underscoresβ€”they can be placed anywhere in a number, including after the last non-underscore character, and are ignored entirely.</p>
diff --git a/docs/spec/primitive.html b/docs/spec/primitive.html
index c3f4ab2f..128fd24f 100644
--- a/docs/spec/primitive.html
+++ b/docs/spec/primitive.html
@@ -4,11 +4,11 @@
<title>Specification: BQN primitives</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-primitives">Specification: BQN primitives</h1>
+<h1 id="specification-bqn-primitives"><a class="header" href="#specification-bqn-primitives">Specification: BQN primitives</a></h1>
<p>Most primitives are specified by the BQN-based implementation in <a href="https://github.com/mlochbaum/BQN/blob/master/spec/reference.bqn">reference.bqn</a>. This document specifies the basic functionality required by those definitions. Descriptions of other primitives are for informational purposes only.</p>
-<h2 id="pervasive-primitives">Pervasive primitives</h2>
+<h2 id="pervasive-primitives"><a class="header" href="#pervasive-primitives">Pervasive primitives</a></h2>
<p>Functions in this section are defined for atoms only; the reference implementations extend them to arrays.</p>
-<h3 id="arithmetic">Arithmetic</h3>
+<h3 id="arithmetic"><a class="header" href="#arithmetic">Arithmetic</a></h3>
<p>BQN uses five arithmetic functions that are standard in mathematics. The precision of these operations should be specified by the number <a href="types.html">type</a>.</p>
<ul>
<li><strong>Add</strong> <code><span class='Function'>+</span></code></li>
@@ -25,7 +25,7 @@
</ul>
<p>In the first two cases, if the result would not be a valid Unicode code point, then an error results. The remaining cases of <code><span class='Function'>+</span></code> and <code><span class='Function'>-</span></code> (adding two characters; negating a character or subtracting it from a number) are not allowed.</p>
<p>Additionally, the <strong>Floor</strong> function <code><span class='Function'>⌊</span></code> returns the largest integer smaller than or equal to the argument, or the argument itself if it is <code><span class='Number'>¯∞</span></code> or <code><span class='Number'>∞</span></code>. It's needed because the arithmetic operations give no fixed-time way to determine if a value is an integer. Floor gives an error if the argument is an atom other than a number.</p>
-<h3 id="comparison">Comparison</h3>
+<h3 id="comparison"><a class="header" href="#comparison">Comparison</a></h3>
<p>Two kinds of comparison are needed to define BQN's primitives: <em>equality</em> comparison and <em>ordered</em> comparison.</p>
<p>Ordered comparison is simpler and is provided by the dyadic Less than or Equal to (<code><span class='Function'>≀</span></code>) function. This function gives an error if either argument is an operation, so it needs to be defined only for numbers and characters. For numbers it is defined by the number system, and for characters it returns <code><span class='Number'>1</span></code> if the left argument's code point is less than that of the right argument. Characters are considered greater than numbers, so that <code><span class='Value'>n</span><span class='Function'>≀</span><span class='Value'>c</span></code> is <code><span class='Number'>1</span></code> and <code><span class='Value'>c</span><span class='Function'>≀</span><span class='Value'>n</span></code> is <code><span class='Number'>0</span></code> if <code><span class='Value'>c</span></code> is a character and <code><span class='Value'>n</span></code> is a number.</p>
<p>The dyadic function <code><span class='Function'>=</span></code>, representing equality comparison, can be applied to any two atoms without an error. Roughly speaking, it returns <code><span class='Number'>1</span></code> if they are indistinguishable within the language and <code><span class='Number'>0</span></code> otherwise. If the two arguments have different types, the result is <code><span class='Number'>0</span></code>; if they have the same type, the comparison depends on type:</p>
@@ -40,7 +40,7 @@
<li>Block instances are equal if they are the same instance.</li>
</ul>
<p>This means that block instance equality indicates identity in the context of mutability: two block instances are equal if any change of state in one would be reflected in the other as well. The concept of identity holds even if the blocks in question have no way of changing or accessing state. For example, <code><span class='Function'>=</span><span class='Modifier2'>β—‹</span><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Separator'>β‹„</span><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Brace'>}}</span><span class='Modifier'>˜</span><span class='String'>@</span></code> is <code><span class='Number'>0</span></code> while <code><span class='Function'>=</span><span class='Modifier'>˜</span><span class='Modifier2'>β—‹</span><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Separator'>β‹„</span><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Brace'>}}</span><span class='String'>@</span></code> is <code><span class='Number'>1</span></code>.</p>
-<h2 id="array-functionality">Array functionality</h2>
+<h2 id="array-functionality"><a class="header" href="#array-functionality">Array functionality</a></h2>
<p>Several subsets of primitives, or dedicated operations, are used to manipulate arrays in the reference implementation.</p>
<ul>
<li><code><span class='Function'>IsArray</span></code> returns <code><span class='Number'>1</span></code> if the argument is an array and <code><span class='Number'>0</span></code> if it's an atom.</li>
@@ -57,23 +57,23 @@
<li><strong>Pick</strong> (<code><span class='Function'>βŠ‘</span></code>) selects the element at index <code><span class='Value'>𝕨</span></code> from list <code><span class='Value'>𝕩</span></code>.</li>
<li><code><span class='Modifier'>_amend</span></code> returns an array identical to list <code><span class='Value'>𝕩</span></code> except that the element at index <code><span class='Value'>𝕗</span></code> is changed to <code><span class='Value'>𝕨</span></code>.</li>
</ul>
-<h2 id="inferred-functionality">Inferred functionality</h2>
+<h2 id="inferred-functionality"><a class="header" href="#inferred-functionality">Inferred functionality</a></h2>
<p>Inferred properties are specified in <a href="inferred.html">their own document</a>, not in the reference implementation.</p>
<ul>
<li><code><span class='Function'>Identity</span></code> gives the identity value for reduction by function <code><span class='Function'>𝕏</span></code>.</li>
<li><strong>Undo</strong> (<code><span class='Modifier'>⁼</span></code>) gives a partial right inverse for function <code><span class='Function'>𝔽</span></code>.</li>
<li><code><span class='Function'>Fill</span></code> gives the enclose of the fill value for array <code><span class='Value'>𝕩</span></code>.</li>
</ul>
-<h2 id="other-provided-functionality">Other provided functionality</h2>
+<h2 id="other-provided-functionality"><a class="header" href="#other-provided-functionality">Other provided functionality</a></h2>
<ul>
<li><strong>Assert</strong> (<code><span class='Function'>!</span></code>) causes an error if the argument is not <code><span class='Number'>1</span></code>. If <code><span class='Value'>𝕨</span></code> is provided, it gives a message to be associated with this error (which can be any value, not necessarily a string).</li>
</ul>
<ul>
<li><strong>Catch</strong> (<code><span class='Modifier2'>⎊</span></code>) evaluates <code><span class='Function'>𝔽</span></code> on the arguments <code><span class='Value'>𝕨</span></code> (if present) and <code><span class='Value'>𝕩</span></code>. If <code><span class='Function'>𝔽</span></code> completes without error it returns the result, but if evaluation of <code><span class='Function'>𝔽</span></code> results in an error then the error is suppressed, and Catch evaluates <code><span class='Function'>𝔾</span></code> on the arguments and returns the result. Errors in <code><span class='Function'>𝔾</span></code> are not caught. Catch only prevents evaluation errors, and not syntax errors: these are considered errors in the program as a whole rather than any particular part of it.</li>
</ul>
-<h2 id="commentary-on-other-primitives">Commentary on other primitives</h2>
+<h2 id="commentary-on-other-primitives"><a class="header" href="#commentary-on-other-primitives">Commentary on other primitives</a></h2>
<p>As noted above, see <a href="https://github.com/mlochbaum/BQN/blob/master/spec/reference.bqn">reference.bqn</a> for the authoritative definitions. Commentary here gives an overall description and highlights implementation subtleties and edge cases.</p>
-<h3 id="combinators">Combinators</h3>
+<h3 id="combinators"><a class="header" href="#combinators">Combinators</a></h3>
<p>There's little to say about BQN's true combinators, since each is simply a pattern of function application. All primitive combinators use their operands as functions, and thus treat a data operand as a constant function.</p>
<ul>
<li><strong>Choose</strong> (<code><span class='Modifier2'>β—Ά</span></code>) is later redefined to use the complete <code><span class='Function'>βŠ‘</span></code> rather than the simple version assumed (using this primitive means it's not a true combinator).</li>
@@ -88,7 +88,7 @@
<li><strong>After</strong>/<strong>Bind</strong> (<code><span class='Modifier2'>⟜</span></code>)</li>
</ul>
<p>The somewhat complicated definition of Valences could be replaced with <code><span class='Brace'>{</span><span class='Function'>𝔽</span><span class='Value'>𝕩;𝕨</span><span class='Function'>𝔾</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code> using headers. However, reference.bqn uses a simple subset of BQN's syntax that doesn't include headers. Instead, the definition relies on the fact that <code><span class='Value'>𝕨</span></code> works like <code><span class='Nothing'>Β·</span></code> if no left argument is given: <code><span class='Paren'>(</span><span class='Number'>1</span><span class='Modifier'>Λ™</span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>-</span><span class='Number'>0</span></code> is <code><span class='Number'>1</span><span class='Function'>-</span><span class='Number'>0</span></code> or <code><span class='Number'>1</span></code> if <code><span class='Value'>𝕨</span></code> is present and <code><span class='Paren'>(</span><span class='Number'>1</span><span class='Modifier'>Λ™</span><span class='Nothing'>Β·</span><span class='Paren'>)</span><span class='Function'>-</span><span class='Number'>0</span></code> otherwise: this reduces to <code><span class='Nothing'>Β·</span><span class='Function'>-</span><span class='Number'>0</span></code> or <code><span class='Number'>0</span></code>.</p>
-<h3 id="array-properties">Array properties</h3>
+<h3 id="array-properties"><a class="header" href="#array-properties">Array properties</a></h3>
<p>The reference implementations extend Shape (<code><span class='Function'>β‰’</span></code>) to atoms as well as arrays, in addition to implementing other properties. In all cases, an atom behaves as if it has shape <code><span class='Bracket'>⟨⟩</span></code>. The functions in this section never cause an error.</p>
<ul>
<li><strong>Shape</strong> (<code><span class='Function'>β‰’</span></code>) gives the shape of an array or atom.</li>
@@ -96,7 +96,7 @@
<li><strong>Length</strong> (<code><span class='Function'>β‰ </span></code>) gives the number of major cells, or <code><span class='Number'>1</span></code> for an argument of rank <code><span class='Number'>0</span></code>.</li>
<li><strong>Depth</strong> (<code><span class='Function'>≑</span></code>) gives the nesting depth. It ignores the shapes of arrays, and considering only the depths of their elements.</li>
</ul>
-<h3 id="arithmetic">Arithmetic</h3>
+<h3 id="arithmetic"><a class="header" href="#arithmetic">Arithmetic</a></h3>
<p>Arithmetic functions not already provided are defined in layer 1. These definitions, like the provided functions, apply to atoms only; they should be extended to arrays using the <code><span class='Modifier'>_perv</span></code> modifier from layer 2.</p>
<ul>
<li><strong>Sign</strong> (<code><span class='Function'>Γ—</span></code>) </li>
@@ -109,7 +109,7 @@
<li><strong>Modulus</strong> (<code><span class='Function'>|</span></code>) is an extension of modular division to real numbers. As it uses floor instead of truncation, it's not the same as the <code><span class='Value'>%</span></code> operator from C or other languages when <code><span class='Value'>𝕨</span><span class='Function'>&lt;</span><span class='Number'>0</span></code>.</li>
<li>Comparisons <strong>Less Than</strong> (<code><span class='Function'>&lt;</span></code>), <strong>Greater Than</strong> (<code><span class='Function'>&gt;</span></code>), <strong>Greater Than or Equal to</strong> (<code><span class='Function'>β‰₯</span></code>), and <strong>Not Equals</strong> (<code><span class='Function'>β‰ </span></code>) are defined in terms of the two provided comparisons.</li>
</ul>
-<h3 id="iteration-modifiers">Iteration modifiers</h3>
+<h3 id="iteration-modifiers"><a class="header" href="#iteration-modifiers">Iteration modifiers</a></h3>
<p>Modifiers for iteration are defined in layers 1, 2, and 4. Two 2-modifiers, <code><span class='Modifier2'>βš‡</span></code> and <code><span class='Modifier2'>βŽ‰</span></code>, use a list of numbers obtained by applying the right operand to the arguments in order to control application. This list has one to three elements: if all three are given then they correspond to the monadic, left, and right arguments; if one is given then it controls all three; and if two are given then they control the left argument, and the right and monadic arguments.</p>
<p>The iteration modifiers <code><span class='Modifier'>⌜¨</span><span class='Modifier2'>βš‡</span><span class='Modifier'>˘</span><span class='Modifier2'>βŽ‰</span></code> process elements or cells in index order, that is, according to lexicographic ordering of indices or according to simple numeric ordering of the indices in the Deshaped (<code><span class='Function'>β₯Š</span></code>) arguments. When both arguments are mapped over independently, the left argument is mapped over &quot;first&quot;, or as an outer loop: one part of the left argument is paired with each part of the right in turn, then the next part of the left argument, and so on.</p>
<p><strong>Table</strong> (<code><span class='Modifier'>⌜</span></code>) and <strong>Each</strong> (<code><span class='Modifier'>Β¨</span></code>) map over the elements of arrays to produce result elements. They convert atom arguments to unit arrays. With one argument, the two modifiers are the same; with two, they differ in how they pair elements. Table pairs every element of the left argument with every element of the right, giving a result shape <code><span class='Value'>𝕨</span><span class='Function'>∾</span><span class='Modifier2'>β—‹</span><span class='Function'>β‰’</span><span class='Value'>𝕩</span></code>. Each uses leading axis agreement: it requires one argument's shape to be a prefix of the other's (if the arguments have the same rank, then the shapes must match and therefore be mutual prefixes). This causes each element of the lower-rank argument to correspond to a cell of the higher-rank one; it's repeated to pair it with each element of that cell. The result shape is the shape of the higher-rank argument.</p>
@@ -118,13 +118,13 @@
<p><strong>Fold</strong> (<code><span class='Modifier'>Β΄</span></code>), <strong>Insert</strong> (<code><span class='Modifier'>˝</span></code>), and <strong>Scan</strong> (<code><span class='Modifier'>`</span></code>) repeatedly apply a function between parts of an array. Fold requires the argument to have rank 1 and applies the operand between its elements, while Insert requires it to have rank 1 or more and applies it between the cells. For each of these two functions, the operand is applied beginning at the end of the array, and an <a href="inferred.html#identities">identity</a> value is returned if the array is empty. While these functions reduce multiple values to a single result, Scan returns many results and preserves the shape of its argument. It requires the argument to have rank at least 1, and applies the function between elements along columnsβ€”that is, from one element in a major cell to the one in the same position of the next major cell. This application begins at the first major cell of the array. Scan never uses the identity element of its operand because if the argument is empty then the result, which has the same shape, will be empty as well.</p>
<p>A left argument for any of the three reduction-based modifiers indicates an initial value to be used, so that the first application of the operand function applies not to two values from <code><span class='Value'>𝕩</span></code> but instead to a value from <code><span class='Value'>𝕨</span></code> and a value from <code><span class='Value'>𝕩</span></code>. In Fold and Insert, the entire value <code><span class='Value'>𝕨</span></code> is the initial value, while in Scan, <code><span class='Value'>𝕨</span></code> is an array of initial values, which must have shape <code><span class='Number'>1</span><span class='Function'>↓≒</span><span class='Value'>𝕩</span></code>.</p>
<p><strong>Repeat</strong> (<code><span class='Modifier2'>⍟</span></code>) applies the operand function, or its <a href="inferred.html#undo">inverse</a>, several times in sequence. The right operand must consist only of integer atoms (arranged in arrays of any depth), and each number there is replaced with the application of the left operand that many times to the arguments. If a left argument is present, then it's reused each time, as if it were bound to the operand function. For a negative number <code><span class='Function'>-</span><span class='Value'>n</span></code>, the function is &quot;applied&quot; <code><span class='Function'>-</span><span class='Value'>n</span></code> times by undoing it <code><span class='Value'>n</span></code> times. In both directions, the total number of times the function is applied is the maximum of all numbers present: results must be saved if intermediate values are needed.</p>
-<h3 id="restructuring">Restructuring</h3>
+<h3 id="restructuring"><a class="header" href="#restructuring">Restructuring</a></h3>
<p><strong>Enclose</strong> (<code><span class='Function'>&lt;</span></code>) forms a unit array that contains its argument.</p>
<p><strong>Merge</strong> (<code><span class='Function'>&gt;</span></code>) combines the outer axes of an array of arrays with inner axes: it requires that all elements of its argument have the same shape, and creates an array such that <code><span class='Paren'>(</span><span class='Value'>i</span><span class='Function'>∾</span><span class='Value'>j</span><span class='Paren'>)</span><span class='Function'>βŠ‘&gt;</span><span class='Value'>𝕩</span></code> is <code><span class='Value'>i</span><span class='Function'>βŠ‘</span><span class='Value'>j</span><span class='Function'>βŠ‘</span><span class='Value'>𝕩</span></code>. It also accepts atom elements of <code><span class='Value'>𝕩</span></code>, converting them to unit arrays, or an atom argument, which is returned unchanged. <strong>Solo</strong> and <strong>Couple</strong> (<code><span class='Function'>≍</span></code>) turn one or two arguments into major cells of the result and can be defined easily in terms of Merge.</p>
<p><strong>Join To</strong> (<code><span class='Function'>∾</span></code>) combines its two arguments along an existing initial axis, unless both arguments are units, in which case it creates an axis and is identical to Couple (<code><span class='Function'>≍</span></code>). The arguments must differ in rank by at most 1, and the result rank is equal to the maximum of 1 and the higher argument rank. Each argument with rank less than the result, and each major cell of an argument with rank equal to it, becomes a major cell of the result, with cells from the left argument placed before those from the right. <strong>Join</strong> (<code><span class='Function'>∾</span></code>) generalizes the equal-rank subset of this behavior to an array of values instead of just two. The argument must be an array (unlike Merge), and its elements must all the same rank, which is at least the argument rank. Atom elements are treated as unit arrays. Then &quot;outer&quot; argument axes are matched up with leading &quot;inner&quot; element axes, and elements are joined along these axes. In order to allow this, the length of an element along a particular axis must depend only on the position along the corresponding axis in the argument. An empty argument to Join is return unchanged, as though the element rank is equal to the argument rank.</p>
<p><strong>Deshape</strong> (<code><span class='Function'>β₯Š</span></code>) differs from the provided function (which returns the element list of an array) only in that it accepts an atom, returning a one-element list containing it. <strong>Reshape</strong> (<code><span class='Function'>β₯Š</span></code>) is extended in numerous ways. It accepts any list of natural numbers (including as a unit array or atom) for the left argument and any right argument; <code><span class='Value'>𝕩</span></code> is deshaped first so that it is treated as a list of elements. These elements are repeated cyclically to fill the result array in ravel order. If <code><span class='Value'>𝕩</span></code> is empty then a non-empty requested result shape causes an error. Furthermore, at most one element of <code><span class='Value'>𝕨</span></code> can be a &quot;length code&quot;: one of the primitives <code><span class='Modifier2'>∘</span><span class='Function'>βŒŠβŒ½β†‘</span></code>. In this case, a target length is computed from the number of elements in <code><span class='Value'>𝕩</span></code> divided by the product of the other elements of <code><span class='Value'>𝕨</span></code> (which must not be zero). If the target length is an integer then it is used directly for the length code. Otherwise, an error is given if the length code is <code><span class='Modifier2'>∘</span></code>, and the target length is rounded down if the code is <code><span class='Function'>⌊</span></code> and up if it's <code><span class='Function'>⌽</span></code> or <code><span class='Function'>↑</span></code>. With code <code><span class='Function'>⌽</span></code>, elements are repeated cyclically as usual, but with code <code><span class='Function'>↑</span></code>, the extra elements after each argument element is used are fill values for <code><span class='Value'>𝕩</span></code>.</p>
<p><strong>Transpose</strong> (<code><span class='Function'>⍉</span></code>) reorders axes of its argument to place the first axis last; if the argument has one or fewer axes then it's enclosed if it's an atom and otherwise returned unchanged. <strong>Reorder Axes</strong> (<code><span class='Function'>⍉</span></code>) requires the left argument to be a list or unit of natural numbers, with length at most the rank of the right argument. This list is extended to match the right argument rank exactly by repeatedly appending the least unused natural number (for example, given <code><span class='Number'>1</span><span class='Ligature'>β€Ώ</span><span class='Number'>3</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span><span class='Ligature'>β€Ώ</span><span class='Number'>0</span></code>, <code><span class='Number'>2</span></code> is appended). After extension, it specifies a result axis for each axis of the right argument. There must be no gaps in the list: that is, with the result rank equal to one plus the greatest value present, every result axis must appear at least once. Now each argument axis is &quot;sent to&quot; the specified result axis: in terms of indices, <code><span class='Value'>i</span><span class='Function'>βŠ‘</span><span class='Value'>𝕨</span><span class='Function'>⍉</span><span class='Value'>𝕩</span></code> is <code><span class='Paren'>(</span><span class='Value'>𝕨</span><span class='Function'>⊏</span><span class='Value'>i</span><span class='Paren'>)</span><span class='Function'>βŠ‘</span><span class='Value'>𝕩</span></code> if <code><span class='Value'>𝕨</span></code> is complete. If multiple argument axes correspond to the same result axis, then a diagonal is taken, and it's as long as the shortest of those argument axes. Like Transpose, Reorder Axes encloses <code><span class='Value'>𝕩</span></code> if it's an atom, so that its result is always an array.</p>
-<h3 id="indices-and-selection">Indices and selection</h3>
+<h3 id="indices-and-selection"><a class="header" href="#indices-and-selection">Indices and selection</a></h3>
<p>Each element in an array <code><span class='Value'>s</span><span class='Function'>β₯Š</span><span class='Value'>e</span></code> is associated with an <em>index</em>, which is a list of natural numbers <code><span class='Value'>i</span></code> such that <code><span class='Function'>∧</span><span class='Modifier'>Β΄</span><span class='Value'>i</span><span class='Function'>&lt;</span><span class='Value'>s</span></code>. The list of all indices, which corresponds to the element list <code><span class='Value'>e</span></code>, contains all such lists <code><span class='Value'>i</span></code> in lexicographic order. That is, index <code><span class='Value'>i</span></code> comes before <code><span class='Value'>j</span></code> exactly when the two indices are not the same, and <code><span class='Value'>i</span></code> has the smaller value at the first position where they are unequal. The index of an element along a particular axis <code><span class='Value'>a</span></code> is the value <code><span class='Value'>a</span><span class='Function'>βŠ‘</span><span class='Value'>i</span></code>.</p>
<p><strong>Range</strong> (<code><span class='Function'>↕</span></code>) is extended to apply to a list of natural numbers, in addition to the provided case of a single natural number (an enclosed natural number <code><span class='Value'>𝕩</span></code> should still result in an error). For a list <code><span class='Value'>𝕩</span></code>, the result is an array of shape <code><span class='Value'>𝕩</span></code> in which the value at a given index is that index, as a list of natural numbers. That is, <code><span class='Value'>i</span><span class='Function'>≑</span><span class='Value'>i</span><span class='Function'>βŠ‘β†•</span><span class='Value'>𝕩</span></code> for any list of natural numbers <code><span class='Value'>i</span></code> with <code><span class='Function'>∧</span><span class='Modifier'>Β΄</span><span class='Value'>i</span><span class='Function'>&lt;</span><span class='Value'>𝕩</span></code>.</p>
<p><strong>Pick</strong> (<code><span class='Function'>βŠ‘</span></code>) is extended to array left arguments. In this case, it requires every depth-1 array in the nested structure of <code><span class='Value'>𝕨</span></code> to be a valid index list for <code><span class='Value'>𝕩</span></code>, and every atom to be contained in one of these lists. The result is <code><span class='Value'>𝕨</span></code> with each index list replaced by the element of <code><span class='Value'>𝕩</span></code> at that index. In the simple case where <code><span class='Value'>𝕨</span></code> itself is an index list, the result is the element of <code><span class='Value'>𝕩</span></code> at index <code><span class='Value'>𝕨</span></code>.</p>
@@ -133,14 +133,14 @@
<p><strong>First Cell</strong> (<code><span class='Function'>⊏</span></code>) selects the initial major cell of <code><span class='Value'>𝕩</span></code>, giving an error if <code><span class='Value'>𝕩</span></code> has rank 0 or length 0.</p>
<p><strong>Group</strong> (<code><span class='Function'>βŠ”</span></code>) performs an opposite operation to Select, so that <code><span class='Value'>𝕨</span></code> specifies not the argument index that result values come from, but the result index that argument values go to. The general case is that <code><span class='Value'>𝕨</span></code> is a list of arrays of numbers; if it has depth less than 2 it's converted to this form by first enclosing it if it's an atom, then placing it in a length-1 list. After this transformation, the result rank is <code><span class='Function'>β‰ </span><span class='Value'>𝕨</span></code>, and each result element has rank <code><span class='Paren'>(</span><span class='Function'>β‰ </span><span class='Value'>𝕨</span><span class='Paren'>)</span><span class='Function'>+</span><span class='Paren'>(</span><span class='Function'>=</span><span class='Value'>𝕩</span><span class='Paren'>)</span><span class='Function'>-+</span><span class='Modifier'>Β΄</span><span class='Function'>=</span><span class='Modifier'>Β¨</span><span class='Value'>𝕨</span></code>, with the initial <code><span class='Function'>β‰ </span><span class='Value'>𝕨</span></code> axes corresponding to elements of <code><span class='Value'>𝕨</span></code> and the remainder to trailing axes of <code><span class='Value'>𝕩</span></code>. Each atom in <code><span class='Value'>𝕨</span></code> can be either a natural number or <code><span class='Number'>Β―1</span></code> (which indicates the corresponding position in <code><span class='Value'>𝕩</span></code> will be omitted). If <code><span class='Number'>Β―1</span></code> doesn't appear, the result has the property that each cell of <code><span class='Value'>𝕩</span></code> appears in the corresponding element of <code><span class='Value'>𝕨</span><span class='Function'>⊏</span><span class='Value'>𝕨</span><span class='Function'>βŠ”</span><span class='Value'>𝕩</span></code>. More concretely, the length of the result along axis <code><span class='Value'>a</span></code> is the maximum value in <code><span class='Value'>a</span><span class='Function'>βŠ‘</span><span class='Value'>𝕨</span></code> plus one, or zero if <code><span class='Value'>a</span><span class='Function'>βŠ‘</span><span class='Value'>𝕨</span></code> is empty. Axis <code><span class='Value'>a</span></code> corresponds to <code><span class='Function'>=</span><span class='Value'>a</span><span class='Function'>βŠ‘</span><span class='Value'>𝕨</span></code> axes in <code><span class='Value'>𝕩</span></code>, and an element of the result at position <code><span class='Value'>i</span></code> along this axis contains all positions in <code><span class='Value'>𝕩</span></code> where <code><span class='Value'>i</span><span class='Function'>=</span><span class='Value'>a</span><span class='Function'>βŠ‘</span><span class='Value'>𝕨</span></code>. There may be multiple such positions, and they're arranged along axis <code><span class='Value'>a</span></code> of that result element according to their index order in <code><span class='Value'>𝕩</span></code>. The shapes of components of <code><span class='Value'>𝕨</span></code> must match the corresponding axes of <code><span class='Value'>𝕩</span></code>, except for rank-1 components of <code><span class='Value'>𝕨</span></code>, which can match or have an extra element. This element, which like the others is either a natural number or <code><span class='Number'>Β―1</span></code>, gives the minimum length of the result axis corresponding to the component of <code><span class='Value'>𝕨</span></code> in question, but otherwise does not affect the result. <strong>Group Indices</strong> treats its argument <code><span class='Value'>𝕩</span></code> as a left argument for Group and uses a right argument made up of indices, which is <code><span class='Function'>↕≠</span><span class='Value'>𝕩</span></code> if <code><span class='Value'>𝕩</span></code> has depth 1 and <code><span class='Function'>β†•βˆΎβ‰’</span><span class='Modifier'>Β¨</span><span class='Value'>𝕩</span></code> if it has depth 2. Because the depth-1 case uses atomic indices, <code><span class='Value'>𝕩</span></code> is required to be a list (and it can't be an atom). Much like Range, the result has depth one higher than the argument.</p>
<p><strong>Indices</strong> (<code><span class='Function'>/</span></code>) applies to a list of natural numbers, and returns a list of natural numbers. The result contains <code><span class='Value'>i</span><span class='Function'>βŠ‘</span><span class='Value'>𝕩</span></code> copies of each natural number index <code><span class='Value'>i</span></code> for <code><span class='Value'>𝕩</span></code>, in increasing order.</p>
-<h3 id="structural-manipulation">Structural manipulation</h3>
+<h3 id="structural-manipulation"><a class="header" href="#structural-manipulation">Structural manipulation</a></h3>
<p>Monadic structural functions work on the first axis of the argument, so they require it to have rank at least 1. <strong>Reverse</strong> (<code><span class='Function'>⌽</span></code>) reverses the ordering of the major cells of <code><span class='Value'>𝕩</span></code>. <strong>Nudge</strong> (<code><span class='Function'>Β»</span></code>) shifts them forward, removing the last and placing a major cell made up of fill elements at the beginning, while <strong>Nudge Back</strong> (<code><span class='Function'>Β«</span></code>) does the same in the reverse direction, so it removes the first cell and places fills at the end. <strong>Prefixes</strong> (<code><span class='Function'>↑</span></code>) and <strong>Suffixes</strong> (<code><span class='Function'>↓</span></code>) each return lists with length one higher than <code><span class='Value'>𝕩</span></code>, whose elements are arrays with the same rank as <code><span class='Value'>𝕩</span></code>. For Prefixes, the element of the result at index <code><span class='Value'>i</span></code> contains the first <code><span class='Value'>i</span></code> major cells of <code><span class='Value'>𝕩</span></code> in order, and for Suffixes, it contains all but these major cells.</p>
<p>The remainder of the functions discussed in this section are dyadic. For all of these, an atom value for <code><span class='Value'>𝕩</span></code> is treated as an array by enclosing it before acting, so that the result is never an atom. There are four functions for which <code><span class='Value'>𝕨</span></code> is a list of whole numbersβ€”but an atomic number or enclosed number is also permitted, and treated as a 1-element listβ€”and its elements are matched with leading axes of <code><span class='Value'>𝕩</span></code>. These functions independently manipulate each axis: one way to define such a process is to consider lists running along the axis, where every element of the index is fixed except one. A change to this axis retains the fixed indices, but can move elements from one location to another along the variable index, add fill elements, or split the axis into two axes. A change to a different axis can rearrange these lists along the original axis, but can't affect the placement of elements within them. In the reference implementations, working on leading axes is accomplished using the Cells (<code><span class='Modifier'>˘</span></code>) modifier recursively, so that action on the first axes doesn't use Cells, on the next is affected by Cells once, then twice, and so on.</p>
<p><strong>Rotate</strong> (<code><span class='Function'>⌽</span></code>) is the simplest of these four functions: each element of <code><span class='Value'>𝕨</span></code> gives an amount to rotate the corresponding axis, where a rotation of <code><span class='Value'>r</span></code> moves the element at index <code><span class='Value'>i</span><span class='Function'>+</span><span class='Value'>r</span></code> to <code><span class='Value'>i</span></code> when all indices are taken modulo the length of the axis. <strong>Windows</strong> (<code><span class='Function'>↕</span></code>) splits each axis of <code><span class='Value'>𝕩</span></code> that corresponds to an element of <code><span class='Value'>𝕨</span></code> in two, so that the result has one set of axes corresponding to elements of <code><span class='Value'>𝕨</span></code>, then another, then the unchanged trailing axes. The second set of axes has lengths given by <code><span class='Value'>𝕨</span></code> (which must consist of natural numbers), while the first has lengths <code><span class='Value'>s</span><span class='Function'>Β¬</span><span class='Value'>𝕨</span></code>, where <code><span class='Value'>s</span></code> contains the lengths of leading axes of <code><span class='Value'>𝕩</span></code>. Position <code><span class='Value'>i</span></code> in the first set of axes and <code><span class='Value'>j</span></code> in the second corresponds to <code><span class='Value'>i</span><span class='Function'>+</span><span class='Value'>j</span></code> in the argument, so that fixing one of these positions and varying the other gives a slice of the argument. In both Rotate and Windows, the length of <code><span class='Value'>𝕨</span></code> is at most the rank of <code><span class='Value'>𝕩</span></code>.</p>
<p><strong>Take</strong> (<code><span class='Function'>↑</span></code>) offers several possibilities. The absolute value of <code><span class='Value'>𝕨</span></code> gives the final lengths of the axes in the result. It may be positive to indicate that the axis aligns with <code><span class='Value'>𝕩</span></code> at the beginning, or negative to indicate it aligns at the end. A zero value gives no result elements, so there is no need to consider alignment. If the absolute value of an element of <code><span class='Value'>𝕨</span></code> is smaller than or equal to the corresponding length in <code><span class='Value'>𝕩</span></code>, then the first or last few elements are taken along that axis. If it is larger, then instead fill elements are added to the end (if positive) or beginning (if negative) to make up the difference in length. <strong>Drop</strong> (<code><span class='Function'>↓</span></code>) gives <code><span class='Value'>𝕨</span></code> a similar meaning, but excludes all elements that Take includes (maintaining the order of the retained ones). The result of Drop never uses fill elements. In a case where Take would use fill elements, it would include all positions from <code><span class='Value'>𝕩</span></code>, so Drop should include none of them, and the result will have length <code><span class='Number'>0</span></code> for that axis. Take and Drop are extended to allow an argument with length greater than the rank of <code><span class='Value'>𝕩</span></code>. In this case leading length-1 axes are added to <code><span class='Value'>𝕩</span></code> so that its rank matches <code><span class='Value'>𝕨</span></code> before taking or dropping.</p>
<p><strong>Replicate</strong> (<code><span class='Function'>/</span></code>) is similar to the four dyadic structural functions above, but <code><span class='Value'>𝕨</span></code> gives a list of containing <em>lists</em> of natural numbers, or plain or enclosed natural numbers, instead of a simple list. If <code><span class='Value'>𝕨</span></code> has depth less than <code><span class='Number'>2</span></code>, it's considered to be a single value corresponding to one axis of <code><span class='Value'>𝕩</span></code>, while if it has depth <code><span class='Number'>2</span></code> then it's a list of values. If <code><span class='Value'>𝕨</span></code> is the empty list <code><span class='Bracket'>⟨⟩</span></code> then it is defined to be in the second case despite having a depth of <code><span class='Number'>1</span></code>. On a single axis of <code><span class='Value'>𝕩</span></code> the corresponding value <code><span class='Value'>r</span></code> from <code><span class='Value'>𝕨</span></code> is either a list or a unit: if it's a unit then it is repeated to match the length of that axis of <code><span class='Value'>𝕩</span></code>, and if it's a list it must already have the same length as that axis. Each number in <code><span class='Value'>r</span></code> now specifies the number of times to repeat the corresponding position in <code><span class='Value'>𝕩</span></code>. This is equivalent to calling Indices on <code><span class='Value'>r</span></code> and using the result for selection.</p>
<p><strong>Shift Before</strong> (<code><span class='Function'>Β»</span></code>) and <strong>Shift After</strong> (<code><span class='Function'>Β«</span></code>) are derived from Join To and share most of its behavior. The difference is that only a portion of the result of Join To is returned, matching the length of <code><span class='Value'>𝕩</span></code>. This portion comes from the beginning for Shift Before and the end for Shift After. The only difference in conditions between the shift functions and Join To is that Join To allows the result to have higher rank than <code><span class='Value'>𝕩</span></code>. Shifts do not, so the rank of <code><span class='Value'>𝕩</span></code> be at least 1 and at least as high as <code><span class='Value'>𝕨</span></code>.</p>
-<h3 id="searching">Searching</h3>
+<h3 id="searching"><a class="header" href="#searching">Searching</a></h3>
<p><strong>Match</strong> (<code><span class='Function'>≑</span></code>) indicates whether two values are considered equivalent. It always returns 0 or 1, and never causes an error. If both arguments are atoms then it is identical to <code><span class='Function'>=</span></code>, and if one is an atom and the other an array then it returns 0. If both arguments are arrays then it returns 1 only if they have the same shape and all pairs of corresponding elements match. Fill elements aren't taken into account, so that arrays that match might still differ in behavior. <strong>Not Match</strong> simply returns the complement of Match, <code><span class='Function'>¬≑</span></code>.</p>
<p>Monadic search functions compare the major cells of <code><span class='Value'>𝕩</span></code> to each other. <code><span class='Value'>𝕩</span></code> must have rank at least 1. Except for Deduplicate (<code><span class='Function'>⍷</span></code>), the result is a list of numbers with the same length as <code><span class='Value'>𝕩</span></code>.</p>
<ul>
@@ -156,7 +156,7 @@
<li><strong>Progressive Index of</strong> (<code><span class='Function'>βŠ’</span></code>) processes non-principal cells in ravel order, and gives the smallest index of a principal argument cell that matches the cell that hasn't already been included in the result. Again <code><span class='Function'>β‰ </span><span class='Value'>𝕨</span></code> is returned for a given cell if there is no valid cell.</li>
</ul>
<p><strong>Find</strong> (<code><span class='Function'>⍷</span></code>) indicates positions where <code><span class='Value'>𝕨</span></code> appears as a contiguous subarray of a <code><span class='Function'>=</span><span class='Value'>𝕨</span></code>-cell of <code><span class='Value'>𝕩</span></code>. It has one result element for each such subarray of <code><span class='Value'>𝕩</span></code>, whose value is 1 if that subarray matches <code><span class='Value'>𝕩</span></code> and 0 otherwise. Find cannot result in an error unless the rank of <code><span class='Value'>𝕨</span></code> is higher than that of <code><span class='Value'>𝕩</span></code>. If <code><span class='Value'>𝕨</span></code> is longer along one axis than the corresponding trailing axis of <code><span class='Value'>𝕩</span></code>, then the result has length 0 along that axis. Any atom argument to Find is automatically enclosed.</p>
-<h3 id="sorting">Sorting</h3>
+<h3 id="sorting"><a class="header" href="#sorting">Sorting</a></h3>
<p>Sorting functions are those that depend on BQN's array ordering. There are three kinds of sorting function, with two functions of each kind: one with an upward-pointing glyph that uses an ascending ordering (these function names are suffixed with &quot;Up&quot;), and one with a downward-pointing glyph and the reverse, descending, ordering (&quot;Down&quot;). Below, these three kinds of function are described, then the ordering rules. Except for the right argument of Bins, all arguments must have rank at least 1.</p>
<p><strong>Sort</strong> (<code><span class='Function'>∧∨</span></code>) reorders the major cells of its argument so that a major cell with a lower index comes earlier in the ordering than a major cell with a higher index, or matches it. If it's possible for matching arrays to differ in behavior because of different (including undefined versus defined) fill elements, then these arrays must maintain their ordering (a stable sort is required).</p>
<p><strong>Grade</strong> (<code><span class='Function'>⍋⍒</span></code>) returns a permutation describing the way the argument array would be sorted. For this reason the reference implementations simply define Sort to be selection by the grade. One way to define Grade is as a sorted version of the index list <code><span class='Function'>↕≠</span><span class='Value'>𝕩</span></code>. An index <code><span class='Value'>i</span></code> is ordered according to the corresponding major cell <code><span class='Value'>i</span><span class='Function'>⊏</span><span class='Value'>𝕩</span></code>. However, ties in the ordering are broken by ordering the index values themselves, so that no two indices are ever considered equal, and the result of sorting is well-defined (for Sort this is not an issueβ€”matching cells are truly interchangeable). This property means that a stable sorting algorithm must be used to implement Grade functions. While cells might be ordered ascending or descending, indices are always ordered ascending, so that for example index <code><span class='Value'>i</span></code> is placed before index <code><span class='Value'>j</span></code> if either <code><span class='Value'>i</span><span class='Function'>⊏</span><span class='Value'>𝕩</span></code> comes earlier in the ordering than <code><span class='Value'>j</span><span class='Function'>⊏</span><span class='Value'>𝕩</span></code>, or if they match and <code><span class='Value'>i</span><span class='Function'>&lt;</span><span class='Value'>j</span></code>.</p>
diff --git a/docs/spec/scope.html b/docs/spec/scope.html
index be592157..5576f6c8 100644
--- a/docs/spec/scope.html
+++ b/docs/spec/scope.html
@@ -4,10 +4,10 @@
<title>Specification: BQN variable scoping</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-variable-scoping">Specification: BQN variable scoping</h1>
+<h1 id="specification-bqn-variable-scoping"><a class="header" href="#specification-bqn-variable-scoping">Specification: BQN variable scoping</a></h1>
<p>BQN uses lexical scoping for variables, where scopes correspond roughly to blocks, or pairs of curly braces separated by semicolons. At the top level in a scope, new variables are visible only after they are defined, but in the scopes it contains, all variables defined in that scope are visible. This system is specified more precisely below.</p>
<p>A running BQN program manipulates variables during its <a href="evaluate.html">execution</a>, but it is important to distinguish these variables from the identifiers that refer to them. As defined in the <a href="token.html">tokenization rules</a>, an identifier is a particular kind of token found in a program's source code. The lexical scoping rules in this page define which identifiers are considered the same; these identifiers will refer to the same variables when the program is run. While each variable has only one identifier, an identifier can refer to any number of variables because a new variable is created for that identifier each time its containing scope is instantiated (that is, each time the contents of the block are evaluated).</p>
-<h2 id="identifier-equivalence-with-lexical-scoping">Identifier equivalence with lexical scoping</h2>
+<h2 id="identifier-equivalence-with-lexical-scoping"><a class="header" href="#identifier-equivalence-with-lexical-scoping">Identifier equivalence with lexical scoping</a></h2>
<p>In this section the concept of an identifier's definition, a possibly different instance of that identifier, is specified. The definition determines when identifiers refer to the &quot;same thing&quot;. In concrete terms, identifiers with the same definition all manipulate the same variable in a particular instance of the definition's containing scope.</p>
<p>A <em>scope</em> is a <code><span class='Function'>PROGRAM</span></code>, <code><span class='Value'>brSub</span></code>, <code><span class='Function'>FCase</span></code>, <code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_mCase</span></code>, <code><span class='Modifier'>_mMain</span></code>, <code><span class='Modifier2'>_cCase_</span></code>, <code><span class='Modifier2'>_cMain_</span></code>, or <code><span class='Value'>brNS</span></code> node as defined by the BQN <a href="grammar.html">grammar</a>. An <em>identifier instance</em> is an <code><span class='Value'>s</span></code>, <code><span class='Function'>F</span></code>, <code><span class='Modifier'>_m</span></code>, or <code><span class='Modifier2'>_c_</span></code> node; its <em>containing scope</em> is the &quot;smallest&quot; scope that contains itβ€”the scope that contains the identifier but not any other scopes containing the identifier. An identifier instance is <em>defined</em> when it is contained in the left hand side of an <code><span class='Gets'>←</span></code> assignment expression, that is, the leftmost component of one of the five grammatical rules with <code><span class='Function'>ASGN</span></code>, provided that the <code><span class='Function'>ASGN</span></code> node is <code><span class='String'>&quot;←&quot;</span></code> or <code><span class='String'>&quot;⇐&quot;</span></code>, or in a scope header, that is, a component immediately preceding <code><span class='String'>&quot;:&quot;</span></code>. Each identifier instance in a valid BQN program corresponds to exactly one such defined identifier, called its <em>definition</em>, and two instances are considered to refer to the same identifier if they have the same definition.</p>
<p>Two identifier instances have the <em>same name</em> if their tokens, as strings, match after removing all underscores <code><span class='Modifier2'>_</span></code> and ignoring case (so that the letters a to z are equal to their uppercase equivalents A to Z for this comparison). However, instances with the same name are not necessarily the same identifier, as they must also have the same definition. A defined identifier is a <em>potential definition</em> of another identifier instance if the two have the same name, and either:</p>
@@ -19,16 +19,16 @@
<p>The definition for an identifier is chosen from the potential definitions based on their containing scopes: it is the one whose containing scope does not contain or match the containing scope of any other potential definition. If for any identifier there is no definition, then the program is not valid and results in an error. This can occur if the identifier has no potential definition, and also if two potential definitions appear in the same scope. In fact, under this scheme it is never valid to make two definitions with the same name at the top level of a single scope, because both definitions would be potential definitions for the one that comes second in program order. Both definitions have the same containing scope, and any potential definition must contain or match this scope, so no potential definition can be selected.</p>
<p>The definition of <em>program order</em> for identifier tokens follows the order of BQN <a href="evaluate.html">execution</a>. It corresponds to the order of a particular traversal of the abstract syntax tree for a program. To find the relative ordering of two identifiers in a program, we consider the highest-depth node that they both belong to; in this node they must occur in different components, or that component would be a higher-depth node containing both of them. In most nodes, the program order goes from right to left: components further to the right come earlier in program order. The exceptions are <code><span class='Function'>PROGRAM</span></code>, <code><span class='Function'>BODY</span></code>, <code><span class='Function'>NS_BODY</span></code>, <code><span class='Value'>list</span></code>, <code><span class='Value'>subject</span></code> (for stranding), and body case (<code><span class='Function'>FCase</span></code>, <code><span class='Modifier'>_mCase</span></code>, <code><span class='Modifier2'>_cCase_</span></code>, <code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_mMain</span></code>, <code><span class='Modifier2'>_cMain_</span></code>, <code><span class='Value'>brSub</span></code>, <code><span class='Function'>BrFunc</span></code>, <code><span class='Modifier'>_brMod1</span></code>, and <code><span class='Modifier2'>_brMod2_</span></code>) nodes, in which program order goes in the opposite order, from left to right (some assignment target nodes also contain lists or strands, but their ordering is irrelevant because if two identifiers with the same name appear in such a list, then it can't be a definition).</p>
<p>A subject label is the <code><span class='Value'>s</span></code> term in a <code><span class='Value'>brSub</span></code> node. As part of a header, it can serve as the definition for an identifier. However, it's defined to be a syntax error if another instance of this identifier appears, except in a <code><span class='Function'>Return</span></code> node (which cannot access its value).</p>
-<h3 id="special-names">Special names</h3>
+<h3 id="special-names"><a class="header" href="#special-names">Special names</a></h3>
<p>Special names such as <code><span class='Value'>𝕩</span></code> or <code><span class='Value'>𝕣</span></code> refer to variables, but have no definition and do not use scoping. Instead, they always refer to the immediately enclosing scope, and are defined automatically when the block is evaluated.</p>
<p>The six special names are <code><span class='Value'>π•¨π•©π•—π•˜π•€π•£</span></code>, and the tokens <code><span class='Function'>π•Žπ•π”½π”Ύπ•Š</span></code>, <code><span class='Modifier'>_𝕣</span></code>, and <code><span class='Modifier2'>_𝕣_</span></code> are alternate spellings of these names as described in the <a href="token.html">tokenization rules</a>. Special names may be modified with <code><span class='Gets'>↩</span></code> assignment but cannot appear as the target of other kinds of assignment. Two special names represent the same identifier if they are the same name and appear in the same body. The initial value these names have is defined by the <a href="evaluate.html">evaluation rules</a>; the grammar for blocks ensures that all special names used in a block will be defined (possibly as the special value <code><span class='Nothing'>Β·</span></code> in the case of <code><span class='Value'>𝕨</span></code>).</p>
-<h3 id="imports-and-exports">Imports and exports</h3>
+<h3 id="imports-and-exports"><a class="header" href="#imports-and-exports">Imports and exports</a></h3>
<p>Names that are preceded by an <code><span class='Value'>atom</span> <span class='String'>&quot;.&quot;</span></code> term, or that appear as <code><span class='Function'>LHS_NAME</span></code> terms in an <code><span class='Function'>NS_VAR</span></code> or <code><span class='Value'>lhsNs</span></code>, are variable references in a namespace: in the first case, the result of the <code><span class='Value'>atom</span></code> node, and in the second, of the overall assignments <code><span class='Value'>subExpr</span></code> right hand side. These names do not follow lexical scoping; in general they must be stored in order to perform a name lookup when the namespace is available. Such a name in <code><span class='Value'>lhsNs</span></code>, or in <code><span class='Function'>NS_VAR</span></code> with no accompanying <code><span class='Value'>lhs</span> <span class='String'>&quot;⇐&quot;</span></code> term, additionally serves as an identifier within the actual enclosing scope, which works like any other assignment.</p>
<p>An identifier is <em>exported</em> if the <code><span class='Function'>ASGN</span></code> node in its definition is <code><span class='String'>&quot;⇐&quot;</span></code>, or if it appears anywhere in an <code><span class='Function'>EXPORT</span></code> term. An identifier can only be exported in the scope where it is defined, and not in a containing scope. An <code><span class='Function'>EXPORT</span></code> term that includes an identifier from such a scope causes an error.</p>
-<h2 id="variables">Variables</h2>
+<h2 id="variables"><a class="header" href="#variables">Variables</a></h2>
<p>A <em>variable</em> is an entity that permits two operations: it can be <em>set</em> to a particular value, and its <em>value</em> can be obtained, resulting in the last value it was set to. When either operation is performed it is referred to as <em>accessing</em> the variable.</p>
<p>When a body in a block is evaluated, it creates a <em>namespace</em>, which contains a variable for each definition (that is, defined identifier instance) the body contains. Whenever another blockβ€”the block itself, not its contentsβ€”is evaluated during the execution of the block, it is linked to the currently-evaluating block, so that it will use the variables defined in this instance. By following these links repeatedly, an instance of a block is always linked to exactly one instance of each block that contains it. These links form a tree that is not necessarily related to the call stack of functions and modifiers. Using the links, the variable an identifier refers to is the one corresponding to that variable's definition in the linked instance of the containing scope for the definition.</p>
<p>The first access to a variable must be made by its definition (this also means it sets the variable). If a different instance of its identifier accesses it first, then an error results. This can happen because every scope contained in a particular scope sees all the definitions it uses, and such a scope could be called before the definition is run. Because of conditional execution, this property must be checked at run time in general; however, in cases where it is possible to statically determine that a program will always violate it, a BQN instance can give an error at compile time rather than run time.</p>
<p>A namespace defines a mapping from names to variables: if the given name is shared by an exported identifier in the body used to create that namespace, then that name maps to the variable corresponding to that identifier. The mapping is undefined for other names.</p>
-<h2 id="returns">Returns</h2>
+<h2 id="returns"><a class="header" href="#returns">Returns</a></h2>
<p>The name <code><span class='Function'>NAME</span> <span class='Function'>|</span> <span class='String'>&quot;π•Š&quot;</span> <span class='Function'>|</span> <span class='String'>&quot;𝕣&quot;</span></code> in a <code><span class='Function'>Return</span></code> node is resolved exactly like any other identifier. Following resolution, the block that defines the identifier must not be a namespace block (export variables or contain an <code><span class='Function'>EXPORT</span></code> statement). Furthermore, if it is a <code><span class='Function'>NAME</span></code>, then its definition must be an internal name for a containing block: <code><span class='Value'>s</span></code> in <code><span class='Value'>brSub</span></code>, <code><span class='Function'>F</span></code> in <code><span class='Function'>FuncHead</span></code> or <code><span class='Function'>FMain</span></code>, <code><span class='Modifier'>_m</span></code> in <code><span class='Function'>Mod1H1</span></code> or <code><span class='Modifier'>_mMain</span></code>, or <code><span class='Modifier2'>_c_</span></code> in <code><span class='Function'>Mod2H1</span></code> or <code><span class='Modifier2'>_cMain_</span></code>. When reached, the <code><span class='Function'>Return</span></code> node's identifier is not accessed; instead, it is used to indicate the namespace that contains it, and through this the block evaluation that created that namespace.</p>
diff --git a/docs/spec/system.html b/docs/spec/system.html
index 53cde76c..76d36a2f 100644
--- a/docs/spec/system.html
+++ b/docs/spec/system.html
@@ -4,11 +4,11 @@
<title>Specification: BQN system-provided values</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-system-provided-values">Specification: BQN system-provided values</h1>
+<h1 id="specification-bqn-system-provided-values"><a class="header" href="#specification-bqn-system-provided-values">Specification: BQN system-provided values</a></h1>
<p>This portion of the spec is still potentially subject to major changes.</p>
<p>The <code><span class='Value'>β€’</span></code> symbol is used to access values other than primitives provided by BQN.</p>
<p>All system values described in the BQN specification are optional: an implementation does not have to include any of them. However, if a system value with one of the names given below is included, then it must have the specified behavior. For namespaces this rule applies to individual fields as well: a namespace may be provided with only some of the fields, but a field with one of the given names must behave as specified.</p>
-<h2 id="execution-and-scope-manipulation">Execution and scope manipulation</h2>
+<h2 id="execution-and-scope-manipulation"><a class="header" href="#execution-and-scope-manipulation">Execution and scope manipulation</a></h2>
<table>
<thead>
<tr>
@@ -37,7 +37,7 @@
</table>
<p>The effect of <code><span class='Function'>β€’Eval</span></code> should be the same as if its argument were written as source code in the scope where <code><span class='Function'>β€’Eval</span></code> appears. It can define variables, and modify those in the current scope or a parent.</p>
<p><code><span class='Function'>β€’ScopedEval</span></code> creates as new scope for evaluation as it is loaded. Other than its syntactic role, it is effectively equivalent to <code><span class='Brace'>{</span><span class='Function'>β€’Eval</span><span class='Brace'>}</span></code>. Parent scopes are visible from the created scope; to make a scope without this property use <code><span class='Function'>β€’BQN</span><span class='String'>&quot;β€’Eval&quot;</span></code> or <code><span class='Function'>β€’BQN</span><span class='String'>&quot;β€’ScopedEval&quot;</span></code>.</p>
-<h2 id="scripts">Scripts</h2>
+<h2 id="scripts"><a class="header" href="#scripts">Scripts</a></h2>
<table>
<thead>
<tr>
@@ -74,11 +74,11 @@
<p><code><span class='Value'>β€’path</span></code> simply gives the path of the file in which it appears. It includes a trailing slash but not the name of the file itself.</p>
<p><code><span class='Value'>β€’name</span></code> gives the name, including the extension, of the file in which it appears. It doesn't include the path.</p>
<p><code><span class='Function'>β€’Exit</span></code> immediately terminates the running BQN process. If the argument is a valid return code (on Unix, an integer), it is returned; otherwise, the default return code (the one returned when the end of the program is reached) is used.</p>
-<h2 id="files">Files</h2>
+<h2 id="files"><a class="header" href="#files">Files</a></h2>
<p>The system namespace value <code><span class='Value'>β€’file</span></code> deals with file operations. For the purposes of <code><span class='Value'>β€’file</span></code>, paths in the filesystem are always strings. As with <code><span class='Function'>β€’Import</span></code>, file paths may be relative or absolute, and relative paths are relative to <code><span class='Value'>β€’path</span></code>, except in <code><span class='Value'>β€’file.</span><span class='Function'>At</span></code> which allows <code><span class='Value'>𝕨</span></code> to specify an alternate base directory. The value <code><span class='Value'>β€’path</span></code> used for a particular instance of <code><span class='Value'>β€’file</span></code> is determined by the file that contains that instance.</p>
<p>When a <code><span class='Value'>β€’file</span></code> function returns a file path or portion of a path, the path is always absolute and canonical, with <code><span class='Value'>.</span></code> and <code><span class='Value'>..</span></code> components removed.</p>
<p>Possible fields of <code><span class='Value'>β€’file</span></code> are given in the subsections below.</p>
-<h3 id="file-paths">File paths</h3>
+<h3 id="file-paths"><a class="header" href="#file-paths">File paths</a></h3>
<p>The following functions manipulate paths and don't access files. Each takes a relative or absolute path <code><span class='Value'>𝕩</span></code>, and <code><span class='Function'>At</span></code> may also take a base directory <code><span class='Value'>𝕨</span></code>.</p>
<table>
<thead>
@@ -118,7 +118,7 @@
</tr>
</tbody>
</table>
-<h3 id="file-metadata">File metadata</h3>
+<h3 id="file-metadata"><a class="header" href="#file-metadata">File metadata</a></h3>
<p>Metadata functions may query information about a file or directory but do not read to or write from it. Each takes a path <code><span class='Value'>𝕩</span></code>, and some functions also allow new data in <code><span class='Value'>𝕨</span></code>. The returned data in any case is the specified property.</p>
<table>
<thead>
@@ -172,7 +172,7 @@
<li><code><span class='String'>'b'</span></code>: Block device</li>
<li><code><span class='String'>'c'</span></code>: Character device</li>
</ul>
-<h3 id="file-access">File access</h3>
+<h3 id="file-access"><a class="header" href="#file-access">File access</a></h3>
<p>File access functions read or write files, either by manipulating files as a whole or interacting with the contents. Whole-file functions cannot overwrite target files: that is, <code><span class='Function'>Rename</span></code> and <code><span class='Function'>Copy</span></code> must give an error if a file exists at <code><span class='Value'>𝕨</span></code>, and <code><span class='Function'>CreateDir</span></code> if a file exists at <code><span class='Value'>𝕩</span></code>, while <code><span class='Function'>Chars</span></code>, <code><span class='Function'>Lines</span></code>, and <code><span class='Function'>Bytes</span></code> can overwrite the contents of an existing file <code><span class='Value'>𝕨</span></code>. However, these three functions must give an error if <code><span class='Value'>𝕨</span></code> exists and is a directory.</p>
<table>
<thead>
@@ -255,8 +255,8 @@
</tr>
</tbody>
</table>
-<h3 id="open-file-object">Open file object</h3>
-<h2 id="input-and-output">Input and output</h2>
+<h3 id="open-file-object"><a class="header" href="#open-file-object">Open file object</a></h3>
+<h2 id="input-and-output"><a class="header" href="#input-and-output">Input and output</a></h2>
<table>
<thead>
<tr>
@@ -285,7 +285,7 @@
</table>
<p><code><span class='Function'>β€’Out</span></code> prints a string to stdout, with a trailing newline. <code><span class='Function'>β€’Show</span></code> displays a BQN value to the programmer (the representation is not specified, and does not need to be plain text). <code><span class='Function'>β€’Fmt</span></code> returns a string (not a character table: lines are separated by linefeeds) indicating how <code><span class='Value'>𝕩</span></code> would be printed by the interactive environment. Both <code><span class='Function'>β€’Show</span></code> and <code><span class='Function'>β€’Fmt</span></code> may take a left argument configuring how the value should be formatted.</p>
<p><code><span class='Function'>β€’Repr</span></code> attempts to return a string so that <code><span class='Function'>β€’BQN</span> <span class='Function'>β€’Repr</span> <span class='Value'>𝕩</span></code> matches <code><span class='Value'>𝕩</span></code>. If <code><span class='Value'>𝕩</span></code> contains any mutable values (operations or namespaces), this is not possible. However, if such a values is stateless, in the sense that they don't access variables outside of their own scopes, it is permissible for <code><span class='Function'>β€’Repr</span></code> to return source code that would create a value with identical behavior.</p>
-<h2 id="operation-properties">Operation properties</h2>
+<h2 id="operation-properties"><a class="header" href="#operation-properties">Operation properties</a></h2>
<table>
<thead>
<tr>
@@ -411,7 +411,7 @@
</tr>
</tbody>
</table>
-<h2 id="time">Time</h2>
+<h2 id="time"><a class="header" href="#time">Time</a></h2>
<table>
<thead>
<tr>
diff --git a/docs/spec/token.html b/docs/spec/token.html
index e2b851a3..11e661f9 100644
--- a/docs/spec/token.html
+++ b/docs/spec/token.html
@@ -4,7 +4,7 @@
<title>Specification: BQN token formation</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-token-formation">Specification: BQN token formation</h1>
+<h1 id="specification-bqn-token-formation"><a class="header" href="#specification-bqn-token-formation">Specification: BQN token formation</a></h1>
<p>This page describes BQN's token formation rules (token formation is also called scanning). Most tokens in BQN are a single character long, but quoted characters and strings, identifiers, and numbers can consist of multiple characters, and comments, spaces, and tabs are discarded during token formation.</p>
<p>BQN source code should be considered as a series of unicode code points, which we refer to as &quot;characters&quot;. The separator between lines in a file is considered to be a single character, newline, even though some operating systems such as Windows typically represent it with a two-character CRLF sequence. Implementers should note that not all languages treat unicode code points as atomic, as exposing the UTF-8 or UTF-16 representation instead is common. For a language such as JavaScript that uses UTF-16, the double-struck characters <code><span class='Value'>𝕨</span><span class='Function'>π•Ž</span><span class='Value'>𝕩</span><span class='Function'>𝕏</span><span class='Value'>𝕗</span><span class='Function'>𝔽</span><span class='Value'>π•˜</span><span class='Function'>𝔾</span></code> are represented as two 16-bit surrogate characters, but BQN treats them as a single unit.</p>
<p>A BQN <em>character literal</em> consists of a single character between single quotes, such as <code><span class='String'>'a'</span></code>, and a <em>string literal</em> consists of any number of characters between double quotes, such as <code><span class='String'>&quot;&quot;</span></code> or <code><span class='String'>&quot;abc&quot;</span></code>. Character and string literals take precedence with comments over other tokenization rules, so that <code><span class='Comment'>#</span></code> between quotes does not start a comment and whitespace between quotes is not removed, but a quote within a comment does not start a character literal. Almost any character can be included directly in a character or string literal without escaping. The only exception is the double quote character <code><span class='String'>&quot;</span></code>, which must be written twice to include it in a string, as otherwise it would end the string instead. Character literals require no escaping at all, as the length is fixed. In particular, literals for the double and single quote characters are written <code><span class='String'>'''</span></code> and <code><span class='String'>'&quot;'</span></code>, while length-1 strings containing these characters are <code><span class='String'>&quot;'&quot;</span></code> and <code><span class='String'>&quot;&quot;&quot;&quot;</span></code>.</p>
diff --git a/docs/spec/types.html b/docs/spec/types.html
index ea44bb76..ce432dbd 100644
--- a/docs/spec/types.html
+++ b/docs/spec/types.html
@@ -4,7 +4,7 @@
<title>Specification: BQN types</title>
</head>
<div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">spec</a></div>
-<h1 id="specification-bqn-types">Specification: BQN types</h1>
+<h1 id="specification-bqn-types"><a class="header" href="#specification-bqn-types">Specification: BQN types</a></h1>
<p>BQN programs manipulate data of seven types:</p>
<ul>
<li>Character</li>