aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorMarshall Lochbaum <mwlochbaum@gmail.com>2022-06-07 22:16:01 -0400
committerMarshall Lochbaum <mwlochbaum@gmail.com>2022-06-07 22:16:01 -0400
commitbed78fe6147cb7921b7367960d406d28d37cb019 (patch)
tree5fd5f3ad00bfbd66b19aabc4a3d688815754be1e /doc
parent07be54d8179ba799cc55dacd2c79fb2292477030 (diff)
The editing is going to end at some point isn't it?
Diffstat (limited to 'doc')
-rw-r--r--doc/leading.md2
-rw-r--r--doc/primitive.md2
-rw-r--r--doc/scan.md4
-rw-r--r--doc/search.md12
-rw-r--r--doc/select.md10
-rw-r--r--doc/selfcmp.md32
-rw-r--r--doc/shape.md6
7 files changed, 32 insertions, 36 deletions
diff --git a/doc/leading.md b/doc/leading.md
index 347d0b65..c564f909 100644
--- a/doc/leading.md
+++ b/doc/leading.md
@@ -8,7 +8,7 @@ Several primitive functions manipulate the right argument, or sometimes both arg
### Manipulating cells
-Most monadic functions that deal with structure at all (that is, not arithmetic) work only on the first axis of the argument. Usually, they treat it as a list of its [major cells](array.md#cells). The function [Length](shape.md) (`≠`) counts these major cells, while [Prefixes](prefixes.md) (`↑`), Suffixes (`↓`), [Reverse](reverse.md) (`⌽`), and [First Cell](select.md) (`⊏`) move them around. The [Insert](fold.md#insert) (`˝`) and [Scan](scan.md) (`` ` ``) modifiers also yield functions that work along the first axis; [Fold](fold.md) (`´`) requires `𝕩` to be a list but does go along the first (only) axis of that list.
+Most monadic functions that deal with structure at all (that is, not arithmetic) work only on the first axis of the argument. Usually, they treat it as a list of its [major cells](array.md#cells). The function [Length](shape.md) (`≠`) counts these major cells, while [Prefixes](prefixes.md) (`↑`), Suffixes (`↓`), [Reverse](reverse.md) (`⌽`), and [First Cell](select.md#first-cell) (`⊏`) move them around. The [Insert](fold.md#insert) (`˝`) and [Scan](scan.md) (`` ` ``) modifiers also yield functions that work along the first axis; [Fold](fold.md) (`´`) requires `𝕩` to be a list but does go along the first (only) axis of that list.
⊢ a ← 3‿2 ⥊ "abcdef" # An array with three major cells
diff --git a/doc/primitive.md b/doc/primitive.md
index 57c58c6e..b30115ec 100644
--- a/doc/primitive.md
+++ b/doc/primitive.md
@@ -50,7 +50,7 @@ A function call with one argument (prefix) is called "monadic" and one with two
| `/` | [Indices](replicate.md#indices) | [Replicate](replicate.md)
| `⍋` | [Grade Up](order.md#grade) | [Bins Up](order.md#bins)
| `⍒` | [Grade Down](order.md#grade) | [Bins Down](order.md#bins)
-| `⊏` | [First Cell](select.md) | [Select](select.md)
+| `⊏` | [First Cell](select.md#first-cell) | [Select](select.md)
| `⊑` | [First](pick.md#first) | [Pick](pick.md)
| `⊐` | [Classify](selfcmp.md#classify) | [Index of](search.md#index-of)
| `⊒` | [Occurrence Count](selfcmp.md#occurrence-count) | [Progressive Index of](search.md#progressive-index-of)
diff --git a/doc/scan.md b/doc/scan.md
index f87580e4..adfcb26a 100644
--- a/doc/scan.md
+++ b/doc/scan.md
@@ -44,7 +44,7 @@ dim ← ⟨2.5+≠tx,0.75+1⊑ty⟩ ⋄ sh ← ¯2.3‿0
-->
-The 1-modifier Scan (`` ` ``) moves along the first axis of the array `𝕩`, building up an array of results by applying `𝔽` repeatedly beginning with `𝕨` or `⊏𝕩`. It's related to the fold modifiers, and most closely resembles the [APL2-style reduction](fold.md#apl2-reduction) `¨˝`, but it traverses the array in forward rather than reverse index order, and includes all intermediate results of `𝔽` in its output instead of just the final one.
+The 1-modifier Scan (`` ` ``) moves along the first axis of the array `𝕩`, building up an array of results by applying `𝔽` repeatedly beginning with `𝕨` or `⊏𝕩`. It's related to the [fold](fold.md) modifiers, and most closely resembles the [APL2-style reduction](fold.md#apl2-reduction) `¨˝`, but it traverses the array in forward rather than reverse index order, and includes all intermediate results of `𝔽` in its output instead of just the final one.
BQN's Scan is ordered differently from Scan in APL. Both include one result for each non-empty prefix of `𝕩`. In BQN this is a left-to-right fold, so that each new result requires one application of `𝔽`. APL uses right-to-left folds, which matches with reduction, but requires starting over at the end for each new prefix, except in special cases. If needed, this definition can be obtained with a fold on each [prefix](prefixes.md) except the first (which is empty). In the particular case of `-⍀`, that nested solution isn't needed: negate odd-indexed elements and then apply `` +` ``.
@@ -117,7 +117,7 @@ Scan moves along the [leading axis](leading.md) of `𝕩`: vertically, for a tab
+` a
-If `𝕨` is given, it must have the same shape as a major cell of `𝕩` (this is why `𝕨` needs to be enclosed when `𝕩` is a list: in general it's an array). Then the first result cell is found by applying `𝔽` to elements of `𝕨` and `⊏𝕩`, and the computation continues as in the one-argument case for remaining cells.
+If `𝕨` is given, it must have the same shape as a [major cell](array.md#cells) of `𝕩` (this is why `𝕨` needs to be enclosed when `𝕩` is a list: in general it's an array). Then the first result cell is found by applying `𝔽` to elements of `𝕨` and `⊏𝕩`, and the computation continues as in the one-argument case for remaining cells.
3‿2‿1‿0 +` a
diff --git a/doc/search.md b/doc/search.md
index af2c9e7e..a83a8219 100644
--- a/doc/search.md
+++ b/doc/search.md
@@ -44,7 +44,7 @@ defs ← "defs" Enc ("mask"At"id=m") Enc ⟨
-->
-The three search functions are Index of (`⊐`), Progressive Index of (`⊒`), and Member of (`∊`). These are dyadic functions that search one argument ("searched-in") for major cells [matching](match.md) cells from the other ("searched-for"). For example, Index of returns, for each cell in `𝕩`, the index of the first cell in `𝕨` that matches it.
+The three search functions are Index of (`⊐`), Progressive Index of (`⊒`), and Member of (`∊`). These are dyadic functions that search one argument ("searched-in") for major cells [matching](match.md) cells from the other ("searched-for"). For example, Index of returns, for each [cell](array.md#cells) in `𝕩`, the index of the first cell in `𝕨` that matches it.
| | Name | for | in | Return
|:----:|-----------------------|:---:|:---:|-------
@@ -81,7 +81,7 @@ Index of (`⊐`) returns the index of the first occurrence of each entry in `
`𝕩∊𝕨` is the same as `(𝕨⊐𝕩)<≠𝕨`. Note the reversal of arguments! In both `∊` and `⊐`, the open side points to the searched-in argument and the closed side points to the searched-for argument. Relatedly, in Select (`⊏`), the open side points to the selected argument, which is more like the searched-in argument in that its cells are generally accessed out of order (the searched-for argument is most like the selection result `𝕨⊏𝕩`).
-Index of always returns exactly one number, even if there are multiple matches, or no matches at all. To find the indices of all matches, start with [Match](match.md) [Each](map.md), then [Indices](replicate.md#indices) (I didn't mean for it to sound so repetitive! It just happened!).
+Index of always returns exactly one number, even if there are multiple matches, or no matches at all. To find the indices of all matches, start with [Match](match.md) [Each](map.md), then apply [Indices](replicate.md#indices) (I didn't mean for it to sound so repetitive! It just happened!).
/ "letters" ≡¨< 'e' # Many to one
@@ -89,7 +89,7 @@ Index of always returns exactly one number, even if there are multiple matches,
## Progressive Index of
-Progressive Index of (`⊒`), as the name and glyph suggest, is a more sophisticated variant of Index of. Like Index of, it returns either `≠𝕨` or an index of a cell from `𝕨` that matches the given cell of `𝕩`. Unlike Index of, no index except `≠𝕨` can ever be repeated. Progressive Index of returns the index of the first *unused* match, provided there's still one left.
+Progressive Index of (`⊒`), as the name and glyph suggest, is a more sophisticated variant of Index of. Like Index of, it returns either `≠𝕨` or an index of a cell from `𝕨` that matches the given cell of `𝕩`. Unlike Index of, no index can ever be repeated (but `≠𝕨` can). Progressive Index of returns the index of the first *unused* match, provided there's still one left.
"aaa" ⊒ "aaaaa"
@@ -131,7 +131,7 @@ Instead of interpreting `𝕩` as a single element, Index of treats it as a list
stuff ⊐< "string"
-Just as bad, this result has the right information, but is enclosed and could break the program later on. Remember that the result of a search function is *always* an array. We really want the [first](pick.md#first) element.
+This result has the right information, but is enclosed and could break the program later on. Remember that the result of a search function is *always* an array. We really want the [first](pick.md#first) element.
stuff ⊑∘⊐⟜< "string"
@@ -153,7 +153,7 @@ Member of and Index of compute each result number independently, so only the sha
But the searched-in argument doesn't have to be a list either! It can also be an array of higher rank. Rank 0 isn't allowed: if you want to "search" a unit, you're probably just looking for [match](match.md).
-The searched-in argument is treated as a list of its major cells. It's the rank of these major cells—let's call this rank `c`—that determines how the searched-for argument is treated. That argument must have rank `c` or more, and it's treated as an array of `c`-cells. For example, if the left argument to `⊐` is a rank-2 table, then each 1-cell (row) of `𝕩` is searched for independently, yielding one number in the result: a 0-cell.
+The searched-in argument is treated as a list of its [major cells](array.md#cells). It's the rank of these major cells—let's call this rank `c`—that determines how the searched-for argument is treated. That argument must have rank `c` or more, and it's treated as an array of `c`-cells. For example, if the left argument to `⊐` is a rank-2 table, then each 1-cell (row) of `𝕩` is searched for independently, yielding one number in the result: a 0-cell.
⊢ rows ← >"row"‿"rho"‿"row"‿"rue"
@@ -161,7 +161,7 @@ The searched-in argument is treated as a list of its major cells. It's the rank
So the result rank of `⊐` is always `𝕨¬○=𝕩`, with a result shape `(1-˜=𝕨)↓≢𝕩`, and `𝕨⊐𝕩` fails if `1>=𝕩` or the result rank would be negative. In the list case, we have `1==𝕩` (so the first condition holds), and the result rank resolves to `=𝕨` (which can't be negative, so the second holds as well). The cell rank of `𝕩` is 0, and the fact that a 0-cell of `𝕩` gives a 0-cell of the result is what causes the shape arithmetic to be so simple.
-For Member of, the arguments are reversed relative to Index of, but otherwise everything's the same. This differs from APL, where entries are always elements, not cells. Many APL designers consider the APL definition to be a failure of foresight and would prefer BQN's definition—or rather A+'s or J's definition, as these languages were actually the first to use it. The rank-aware version is more flexible, as it allows both searching for elements and searching for rows. APL would return the first result in both cases.
+For Member of, the arguments are reversed relative to Index of, but otherwise everything's the same. This differs from APL, where entries are always elements, not cells. Many APL designers consider the APL definition to be a failure of foresight and would prefer BQN's definition—or rather A+'s or J's definition, as these languages were actually the first to use it. The rank-aware version is more flexible, as it allows both searching for elements and searching for rows. APL would return the first result in both cases below.
(2‿1≍3‿1) ∊ 3‿1‿4‿3
diff --git a/doc/select.md b/doc/select.md
index 4b0af7f4..20303956 100644
--- a/doc/select.md
+++ b/doc/select.md
@@ -38,7 +38,7 @@ The monadic form First Cell (`⊏`) gets the major cell with index 0, so that `
## Single selection
-Each axis of a BQN array is numbered starting at zero. Major cells are arranged along the first axis; in accordance with the [leading axis](leading.md) principle, Select returns a major cell of `𝕩` when `𝕨` is an atom.
+The [major cells](array.md#cells) of an array are arranged along the [first axis](leading.md) and numbered starting at 0. For a natural number `𝕨`, Select returns the major cell of `𝕩` with index `𝕨`.
2 ⊏ "abcdef" # An enclosed element
@@ -48,7 +48,7 @@ Each axis of a BQN array is numbered starting at zero. Major cells are arranged
0 ⊏ <5 # No first axis to select from
-As a major cell of `𝕩`, the result has rank one less than it and its shape is `1↓≢𝕩`. `𝕩` must have rank one or more.
+As a major cell, the result has rank one less than `𝕩` and shape `1↓≢𝕩`. Of course `𝕩` must have at least one axis to select along, or there are no major cells and you'll get an error.
The index `𝕨` has to be an integer less than `≠𝕩`. It can be negative, in which case it must be greater than or equal to `-≠𝕩`. Negative indices select from the end of `𝕩`, in that `¯1` indicates the last major cell and `-≠𝕩` indicates the first. If `≠𝕩` is 0, then no index is valid.
@@ -56,6 +56,8 @@ The index `𝕨` has to be an integer less than `≠𝕩`. It can be negative, i
0 ⊏ ""
+### First Cell
+
The monadic case First Cell (`⊏𝕩`) is identical to `0⊏𝕩`. It has the same restrictions: `𝕩` must have rank 1 or more, and length 1 or more.
⊏ "abc"
@@ -68,7 +70,7 @@ The monadic case First Cell (`⊏𝕩`) is identical to `0⊏𝕩`. It has the s
## First-axis selection
-If `𝕨` is an array of numbers (including any empty array), then each number indicates a major cell of `𝕩`. In the simplest case, a list of numbers gives a result with the same rank as `𝕩` but maybe not the same length.
+If `𝕨` is an array of numbers (including any empty array), then each number indicates a major cell of `𝕩`. In the simplest case, a list of numbers gives a result with the same rank as `𝕩` but the length of `𝕨`.
2‿3‿3‿0‿4‿1 ⊏ "OlZEt"
@@ -117,4 +119,4 @@ However, the `<¨⊸⊏` construct can select a cell of any rank from `𝕩`, be
If an element of `𝕨` has rank more than 1, it increases the rank of `𝕩` rather than decreasing it. The general rule is that in the result, one axis of `𝕩` is replaced by all the axes of the corresponding element of `𝕨` (trailing axes are unchanged). So the final shape `≢𝕨⊏𝕩` is `(∾≢¨𝕨)∾𝕨≠⊸↓≢𝕩`. But this shape doesn't affect the elements retrieved from `𝕩`. In all cases, using `⥊¨𝕨` for the left argument and then [reshaping](reshape.md) the result would yield the same value.
-Selection only ever applies to leading axes of `𝕩`. However, you can skip some leading axes using `˘` or `⎉`, to select on any contiguous set of axes. In particular, use the one-axis case `𝕨⊸⊏⎉(-k) 𝕩` to select along axis `k` of `𝕩`.
+Selection only ever applies to leading axes of `𝕩`. However, you can skip some leading axes using [Rank](rank.md) modifiers `˘` or `⎉`, to select on any contiguous set of axes. In particular, use the one-axis case `𝕨⊸⊏⎉(-k) 𝕩` to select along axis `k` of `𝕩`.
diff --git a/doc/selfcmp.md b/doc/selfcmp.md
index 41114a1d..bc9154a8 100644
--- a/doc/selfcmp.md
+++ b/doc/selfcmp.md
@@ -39,7 +39,7 @@ defs ← "defs" Enc ("mask"At"id=m") Enc ⟨
-->
-BQN has four self-search functions, Classify (`⊐`), Occurrence Count (`⊒`), Mark Firsts (`∊`), and Deduplicate (`⍷`). Each of these is a monadic function that obtains its result by comparing each major cell of the argument (which must have rank at least 1) to the earlier major cells with [match](match.md). For example, Mark Firsts indicates the cells that don't match any earlier cell, making them the first of their kind.
+BQN has four self-search functions, Classify (`⊐`), Occurrence Count (`⊒`), Mark Firsts (`∊`), and Deduplicate (`⍷`). Each of these is a monadic function that obtains its result by comparing each [major cell](array.md#cells) of the argument (which must have rank at least 1) to the earlier major cells with [match](match.md). For example, Mark Firsts indicates the cells that don't match any earlier cell, which might be called the first of their kind.
∊ "abaacb"
@@ -50,6 +50,14 @@ When the argument is a list, its major cells are units and thus contain one elem
The result has one number for each major cell, or in other words is a list with the same length as its argument. Three self-search functions follow this pattern, but Deduplicate (`⍷`) is different: it returns an array of the same rank but possibly a shorter length than the argument.
+### Deduplicate
+
+Deduplicate removes every major cell from the argument that matches an earlier cell, resulting in an array with the same rank but possibly a shorter length. It might also be described as returning the unique major cells of the argument, ordered by first occurrence. Deduplicate [Under](under.md) [Reverse](reverse.md) (`⍷⌾⌽`) orders by last occurrence instead.
+
+ ⍷ >"take"‿"drop"‿"drop"‿"pick"‿"take"‿"take"
+
+ ⍷⌾⌽ >"take"‿"drop"‿"drop"‿"pick"‿"take"‿"take"
+
## Classify
Classify is the universal self-search function, in that it preserves all the self-search information in its argument. It gives each different cell value a natural number, ordered by first appearance.
@@ -75,21 +83,19 @@ Classify is also related to [Deduplicate](#deduplicate). In a way they are compl
⍷ ⊐ c
⊐ ⍷ c
-Applying both separately, in contrast, gives completely interesting results. These results contain all information from the original argument, as `⍷` indicates which cells it contained and `⊐` indicates where they were located. The function [Select](select.md) (`⊏`) reconstructs the argument from the two values.
+Applying both separately is a different story, and gives completely interesting results. These results contain all information from the original argument, as `⍷` indicates which cells it contained and `⊐` indicates where they were located. The function [Select](select.md) (`⊏`) reconstructs the argument from the two values.
⍷ c
⊐ c
(⊐c) ⊏ (⍷c)
-One way to view this relationship is to consider an idea from linear algebra, where an idempotent transformation is called a "projection". That means that the argument might be any value but the result is part of a smaller class of values, and any argument from that smaller class is left the same. What arrays do the two functions project to? The result of Deduplicate is an array with no repeated major cells. The result of Classify is a list of natural numbers, but it also has an additional property: each number in the list is at most one higher than the previous numbers, and the first number is zero. This comes from the way Classify numbers the cells of its argument. When it finds a cell that hasn't appeared before (at a lower index), it always chooses the next higher number for it.
+One way to view this relationship is from the perspective of linear algebra, where an idempotent transformation is called a "projection". That means that the argument might be any value but the result is part of a smaller class of values, and any argument from that smaller class is left the same. What arrays do the two functions project to? The result of Deduplicate is an array with no repeated major cells. The result of Classify is a list of natural numbers, but it also has an additional property: each number in the list is at most one higher than the previous numbers, and the first number is zero. This comes from the way Classify numbers the cells of its argument. When it finds a cell that hasn't appeared before (at a lower index), it always chooses the next higher number for it.
-Applying both Classify and Deduplicate gives an array that has both properties (this isn't the case for all pairs of projections—we need to know that Classify maintains the uniqueness property for Deduplicate and vice-versa). It has no duplicate major cells, *and* it's a list of natural numbers that starts with 0 and never goes up by more than one. Taken together, these are a tight constraint! The first element of the argument has to be 0. The next can't be 0 because it's already appeared, but it can't be more than one higher—it has to be 1. The next can't be 0 or 1, and has to be 2. And so on. So the result is always `↕n` for some `n`. In fact it's possible to determine the length as well, by noting that each function preserves the number of unique major cells in its argument. Classify does this because distinct numbers in the output correspond exactly to distinct major cells in the input; Deduplicate does this because it only removes duplicate cells, not distinct ones. So the final result is `↕n`, where `n` is the number of unique major cells in the argument.
+Applying both Classify and Deduplicate gives an array that has both properties (this isn't the case for all pairs of projections—we need to know that Classify maintains the uniqueness property for Deduplicate and vice-versa). It has no duplicate major cells, *and* it's a list of natural numbers that starts with 0 and never goes up by more than one. Taken together, these are a tight constraint! The first element of the argument has to be 0. The next can't be 0 because it's already appeared, but it can't be more than one higher—it has to be 1. The next can't be 0 or 1, and has to be 2. And so on. So the result is always `↕n` for some `n`. It's possible to determine the length as well, by noting that each function preserves the number of unique major cells in its argument. Classify does this because distinct numbers in the output correspond exactly to distinct major cells in the input; Deduplicate does this because it only removes duplicate cells, not distinct ones. So the final result is `↕n`, where `n` is the number of unique major cells in the argument.
### Mark Firsts
-*See the [APL Wiki page](https://aplwiki.com/wiki/Unique_Mask) on this function as well.*
-
-Mark Firsts (`∊`) is the simplest self-search function: it returns `0` for any major cell of the argument that is a duplicate of an earlier cell and `1` for a major cell that's the first with its value. To implement [Deduplicate](#deduplicate) in terms of Mark Firsts, just [filter](replicate.md) out the duplicates with `∊⊸/`.
+Mark Firsts (`∊`) is the simplest numeric self-search function: it returns `0` for any major cell of the argument that is a duplicate of an earlier cell and `1` for a major cell that's the first with its value. To implement [Deduplicate](#deduplicate) in terms of Mark Firsts, just [filter](replicate.md) out the duplicates with `∊⊸/`.
∊ 3‿1‿4‿1‿5‿9‿2‿6‿5
@@ -126,15 +132,3 @@ An interesting combination is Occurrence Count applied to the result of [Indices
⊒ / 2‿3‿4
A more efficient way when `⊒` doesn't have a fast implementation is `` /(¯1⊸⊑↕⊸-⊏⟜»)+` ``, but that's clearly quite a bit more complicated.
-
-### Deduplicate
-
-*There's also an [APL Wiki page](https://aplwiki.com/wiki/Unique) on this function.*
-
-Deduplicate removes every major cell from the argument that matches an earlier cell, resulting in an array with the same rank but possibly a shorter length. It might also be described as returning the unique major cells of the argument, ordered by first occurrence. Deduplicate [Under](under.md) Reverse (`⍷⌾⌽`) orders by last occurrence instead.
-
- ⍷ >"take"‿"drop"‿"drop"‿"pick"‿"take"‿"take"
-
- ⍷⌾⌽ >"take"‿"drop"‿"drop"‿"pick"‿"take"‿"take"
-
-The relationship between Classify and Deduplicate is discussed [above](#classify-and-deduplicate).
diff --git a/doc/shape.md b/doc/shape.md
index 4c45280f..c597f114 100644
--- a/doc/shape.md
+++ b/doc/shape.md
@@ -2,13 +2,13 @@
# Array dimensions
-The function Shape (`≢`) returns an array's shape, and Rank (`=`) and Length (`≠`) return properties that can be derived from the shape. BQN's arrays are multidimensional, so that the shape is a list of natural numbers (the length along each axis), while the rank (length of the shape) and length (of the first axis) are numbers. In these functions, an atom is treated as a unit array, which has rank 0 and empty shape. A unit has no first axis, but its length is defined to be 1.
+The function Shape (`≢`) returns an array's shape, and Rank (`=`) and Length (`≠`) return properties that can be derived from the shape. BQN's [arrays](array.md) are multidimensional, so that the shape is a list of natural numbers (the length along each axis), while the rank (length of the shape) and length (of the first axis) are numbers. In these functions, an atom is treated as a unit array, which has rank 0 and empty shape. A unit has no first axis, but its length is defined to be 1.
Rank can be defined as `≠∘≢` while Length can be defined with a [fold](fold.md) to be `1⊣´≢`.
## Examples
-The function [Reshape](reshape.md) (`⥊`) always returns an array of shape `𝕨`, so we use it to make an array of shape `1‿3‿2‿6` in the example below ([Take](take.md) (`↑`) shares this property if `(≠𝕨)≤=𝕩`).
+The function [Reshape](reshape.md) (`⥊`) always returns an array of shape `𝕨`, so we use it to make an array of shape `1‿3‿2‿6` in the example below ([Take](take.md) (`↑`) shares this property if `(≠𝕨)≥=𝕩`).
⊢ arr ← 1‿3‿2‿6 ⥊ '0'+↕10
@@ -32,7 +32,7 @@ Applying Shape and the other two functions to an atom shows a shape of `⟨⟩`
## Units
-A unit is an atom, or an array with no axes—rank 0. (See [Enclose](enclose.md) for more about unit arrays). Since it doesn't have any axes, its shape should have no elements. It should be the empty list `⟨⟩` (with a fill of `0`, like all shapes). As there's no first element in the shape, it's not obvious what the length should be, and a stricter language would just give an error. However, there are some good reasons to use a length of `1`. First, the total number of elements is 1, meaning that if the length divides this number evenly (as it does for non-unit arrays) then the only possible natural number it can be is 1. Second, many functions that take a list for a particular argument also accept a unit, and treat it as a length-1 array. For example, `5⥊a` and `⟨5⟩⥊a` are identical. Defining `≠5` to be `1` means that `=s⥊a` is always `≠s`.
+A [unit](enclose.md#whats-a-unit) is an atom, or an array with no axes—rank 0. Since it doesn't have any axes, its shape should have no elements. It should be the empty list `⟨⟩` (with a [fill](fill.md) of `0`, like all shapes). As there's no first element in the shape, it's not obvious what the length should be, and a stricter language would just give an error. However, there are some good reasons to use a length of `1`. First, the total number of elements is 1, meaning that if the length divides this number evenly (as it does for non-unit arrays) then the only possible natural number it can be is 1. Second, many functions that take a list for a particular argument also accept a unit, and treat it as a length-1 array. For example, `5⥊a` and `⟨5⟩⥊a` are identical. Defining `≠5` to be `1` means that `=s⥊a` is always `≠s`.
Despite this last point, it's important to remember that a unit isn't the same as a 1-element list. For example, the length-1 string `"a"` doesn't match `<'a'` but instead `⟨'a'⟩`. And also bear in mind that having an empty *shape* doesn't make a unit an empty *array*. That would mean it has no elements, not one!