diff options
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/logic.md | 14 | ||||
| -rw-r--r-- | doc/map.md | 6 | ||||
| -rw-r--r-- | doc/match.md | 9 | ||||
| -rw-r--r-- | doc/namespace.md | 2 | ||||
| -rw-r--r-- | doc/oop.md | 6 | ||||
| -rw-r--r-- | doc/order.md | 8 | ||||
| -rw-r--r-- | doc/prefixes.md | 12 | ||||
| -rw-r--r-- | doc/range.md | 6 | ||||
| -rw-r--r-- | doc/replicate.md | 8 |
9 files changed, 41 insertions, 30 deletions
diff --git a/doc/logic.md b/doc/logic.md index 1e25fd57..8e7f935a 100644 --- a/doc/logic.md +++ b/doc/logic.md @@ -8,6 +8,8 @@ If the arguments are probabilities of independent events, then an extended funct Both valences of `¬` are equivalent to the fork `1+-`. The dyadic valence, called "Span", computes the number of integers in the range from `𝕩` to `𝕨`, inclusive, when both arguments are integers and `𝕩≤𝕨` (note the reversed order, which is used for consistency with subtraction). This function has many uses, and in particular is relevant to the [Windows](windows.md) function. +These functions are considered [arithmetic](arithmetic.md) functions and thus are [pervasive](arithmetic.md#pervasion). + ## Definitions We define: @@ -22,7 +24,7 @@ Note that `¬⁼ ←→ ¬`, since when applying `¬` twice the first added 1 wi ## Examples -We can form truth tables including the non-integer value one-half: +We can form truth [tables](map.md#table) including the non-integer value one-half: ¬ 0‿0.5‿1 @@ -30,18 +32,18 @@ We can form truth tables including the non-integer value one-half: ∨⌜˜ 0‿0.5‿1 -As with logical And and Or, any value and 0 is 0, while any value or 1 is 1. The other boolean values give the identity elements for the two functions: 1 and any value gives that value, as does 0 or the value. +As with logical And and Or, any value and 0 is 0, while any value or 1 is 1. The other boolean values give the identity values for the two functions: 1 and any value gives that value, as does 0 or the value. ## Why not GCD and LCM? The main reason for omitting these functions is that they are complicated and, when applied to real or complex numbers, require a significant number of design decisions where there is no obvious choice (for example, whether to use comparison tolerance). On the other hand, these functions are fairly easy to implement, which allows the programmer to control the details, and also add functionality such as the extended GCD. -A secondary reason is that the GCD falls short as an extension of Or, because its identity element 0 is not total. `0∨x`, for a real number `x`, is actually equal to `|x` and not `x`: for example, `0∨¯2` is `2` in APL. This means the identity `0∨x ←→ x` isn't reliable in APL. +A secondary reason is that the GCD falls short as an extension of Or, because its identity value 0 is not total. `0∨x`, for a real number `x`, is actually equal to `|x` and not `x`: for example, `0∨¯2` is `2` in APL. This means the identity `0∨x ←→ x` isn't reliable in APL. -## Identity elements +## Identity values -It's common to apply `∧´` or `∨´` to a list (checking whether all elements are true and whether any are true, respectively), and so it's important for extensions to And and Or to share their identity element. Minimum and Maximum do match And and Or when restricted to booleans, but they have different identity elements. It would be dangerous to use Maximum to check whether any element of a list is true because `>⌈´⟨⟩` yields `¯∞` instead of `0`—a bug waiting to happen. Always using `0` as a left argument to `⌈´` fixes this problem but requires more work from the programmer, making errors more likely. +It's common to apply a [fold](fold.md) `∧´` or `∨´` to a list (checking whether all elements are true and whether any are true, respectively), and so it's important for extensions to And and Or to share their [identity](fold.md#identity-values) value. [Minimum and Maximum](arithmetic.md#additional-arithmetic) do match And and Or when restricted to booleans, but they have different identity values. It would be dangerous to use Maximum to check whether any element of a list is true because `⌈´⟨⟩` yields `¯∞` instead of `0`—a bug waiting to happen. To avoid this the programmer would have to use an initial value `𝕨` of `0`, which is easy to forget. -It is easy to prove that the bilinear extensions have the identity elements we want. Of course `1∧x` is `1×x`, or `x`, and `0∨x` is `0×⌾¬x`, or `¬1׬x`, giving `¬¬x` or `x` again. Both functions are commutative, so these identities are double-sided. +It's not hard to prove that the bilinear extensions have the identity values we want. Of course `1∧x` is `1×x`, or `x`, and `0∨x` is `0×⌾¬x`, or `¬1׬x`, giving `¬¬x` or `x` again. Both functions are commutative, so these values are identities on the right as well. Other logical identities do not necessarily hold. For example, in boolean logic And distributes over Or and vice-versa: `a∧b∨c ←→ (a∧b)∨(a∧c)`. But substituting `×` for `∧` and `+-×` for `∨` we find that the left hand side is `(a×b)+(a×c)+(a×b×c)` while the right gives `(a×b)+(a×c)+(a×b×a×c)`. These are equivalent for arbitrary `b` and `c` only if `a=a×a`, that is, `a` is 0 or 1. In terms of probabilities the difference when `a` is not boolean is caused by failure of independence. On the left hand side, the two arguments of every logical function are independent. On the right hand side, each pair of arguments to `∧` are independent, but the two arguments to `∨`, `a∧b` and `a∧c`, are not. The relationship between these arguments means that logical equivalences no longer apply. @@ -66,7 +66,7 @@ The applications are performed in index order: index `…0‿0`, then `…0‿1` o←⟨⟩ ⋄ {o∾⟜<↩𝕩}¨ "index"≍"order" ⋄ o -When an array is displayed, index order is the same as the top-to-bottom, left-to-right reading order of English. It's also the same as the ordering of [Deshape](reshape.md#deshape)'s result, so that here `o` ends up being `⥊𝕩`. The dyadic cases described in the following sections will also have a defined evaluation order, but it's not easy to describe it in terms of the arguments: instead, the *result* elements are produced in index order. +When an array is displayed, index order is the same as the top-to-bottom, left-to-right reading order of English. It's also the same as the ordering of [Deshape](reshape.md#deshape)'s result, so that here `o` ends up being `⥊𝕩`. The dyadic cases described in the following sections will also have a defined evaluation order, but it's not as easy to describe it in terms of the arguments: instead, the *result* elements are produced in index order. ## Table @@ -148,11 +148,11 @@ This makes for a lot fewer applications than Table. Only the diagonal elements f 0‿0 ⍉ "ABCD" ≍⌜ "0123" -If the argument lengths don't match then Each gives an error. This contrasts with zip in many languages, which drops elements from the longer argument. This is rarely wanted in BQN, and having an error right away saves debugging time. +If the argument lengths don't match then Each gives an error. This contrasts with zip in many languages, which drops elements from the longer argument (this is natural for linked lists). This flexibility is rarely wanted in BQN, and having an error right away saves debugging time. "ABC" ≍¨ "01234" -Arguments can have any shape as long as the axis lengths match up. As with Table, the result elements don't depend on this shape but the result shape does. +Arguments can have any shape as long as the axis lengths match up. As with Table, the result elements don't depend on these shapes but the result shape does. (>⟨20‿30‿10,50‿40‿60⟩) +⟜↕¨ 2‿1‿0≍3‿2‿1 diff --git a/doc/match.md b/doc/match.md index 96b5c4c9..fdd2e6cc 100644 --- a/doc/match.md +++ b/doc/match.md @@ -7,7 +7,7 @@ The primitive Match (`≡`) tests whether its two argument arrays are considered "abc" ≡ 'a'‿'b'‿'c' 4 ≢ <4 -Match always gives the same result as Equals (`=`) when both arguments are atoms, but the two functions are extended to arrays differently: while Equals maps over array arguments to return an array of results, Match compares them in totality and always returns one boolean (it never gives an error). Match is the basis for BQN's search and self-comparison functions. +Match always gives the same result as [Equals](arithmetic.md#comparisons) (`=`) when both arguments are atoms, but the two functions are extended to arrays differently: while the pervasive Equals maps over array arguments to return an array of results, Match compares them in totality and always returns one boolean (it never gives an error). Match is the basis for BQN's [search](search.md) and [self-comparison](selfcmp.md) functions. "abc" = "acc" "abc" ≡ "acc" @@ -15,7 +15,7 @@ Match always gives the same result as Equals (`=`) when both arguments are atoms "abc" = "ab" # Mismatched shapes "abc" ≡ "ab" -Match compares arrays based on their fundamental properties—shape and elements—and not the [fill element](../spec/inferred.md#fill-elements), which is an inferred property. Since it can be computed differently in different implementations, using the fill element in Match could lead to some confusing results. Even if the implementation doesn't define a fill for `'a'‿'b'‿'c'`, it should still be considered to match `"abc"`. +Match compares arrays based on their fundamental properties—[shape](shape.md) and elements—and not the [fill element](../spec/inferred.md#fill-elements), which is an inferred property. Since it can be computed differently in different implementations, using the fill element in Match could lead to some confusing results. Even if the implementation doesn't define a fill for `'a'‿'b'‿'c'`, it should still be considered to match `"abc"`. To give a precise definition, two arrays are considered to match if they have the same shape and all corresponding elements from the two arrays match. Every array has a finite [depth](depth.md) so this recursive definition always ends up comparing non-arrays, or atoms. An array never matches an atom, so the result if only one argument is an atom is `0`. The interesting case is when both arguments are atoms, discussed below. @@ -30,6 +30,7 @@ Starting with the easiest rules, values with different types are never equal to Two characters are equal when they have the same code point. Numeric equality depends on the number system in use, but probably works about how you expect. If you're coming from APL, note that current BQN implementations don't employ comparison tolerance. To see if two floats are roughly equal you'll need to write a tolerant comparison yourself, but how often do you really need to do this? 'x' = "wxyz" + 1.25 = 1 + 0.25 Mutable types are more difficult. Here there are three cases: @@ -40,7 +41,9 @@ Mutable types are more difficult. Here there are three cases: The first two are fairly similar to how numbers and arrays work. Primitives and compounds like trains, or modifiers with bound operands, are immutable, so they are defined purely by what components they contain. ⟨+,-,×⟩ = ⟨+,-,÷⟩ + ⟨+ - ×⟩ = ⟨+ - ÷⟩ # Compare two three-trains component-wise + ⟨+ - ÷⟩ = ⟨+ - ÷⟩ This approach can't tell you whether two functions are mathematically different—that is, whether they ever return different results given the same arguments (this is an undecidable problem, and also gets confusing since "different" is included in its own definition). However, if two functions compare equal, then they will always return the same results. @@ -50,6 +53,7 @@ This approach can't tell you whether two functions are mathematically different The final point above about block instances is subtler. An instance of a block function or modifier is mutable, meaning that its behavior can change over the course of a program. Consider the following two functions: F‿G ← { a←10 ⋄ {a+𝕩}‿{a↩𝕩} } + F 5 # One result G 8 F 5 # Another result—the definition of insanity! @@ -58,6 +62,7 @@ The final point above about block instances is subtler. An instance of a block f F1 ← F {𝕏 6}¨ F‿F1 + G 3 {𝕏 6}¨ F‿F1 diff --git a/doc/namespace.md b/doc/namespace.md index fc7727df..d677843f 100644 --- a/doc/namespace.md +++ b/doc/namespace.md @@ -25,7 +25,7 @@ Namespaces improve encapsulation by allowing many values to be exported at once. Mutability means that the behavior of one namespace can change over the course of the program. Mutability is often a liability, so make sure you really need it before leaning too heavily on this property. While there's no way to tell from the outside that a particular namespace is mutable, you can tell it isn't if the source code doesn't contain `↩`, as this is the only way it can modify the variables it contains. -A namespace that makes use of mutability is essentially an object: a collection of state along with operations that act on it. Object-oriented programming is the other major use of namespaces. Contrary to the name, there's never a need to orient your programming around objects, and it's perfectly fine to use an object here or there when you need to, for instance to build a mutable queue of values. +A namespace that makes use of mutability is essentially an object: a collection of state along with operations that act on it. [Object-oriented programming](oop.md) is the other major use of namespaces. Contrary to the name, there's never a need to orient your programming around objects, and it's perfectly fine to use an object here or there when you need to, for instance to build a mutable queue of values. ## Exports @@ -46,12 +46,16 @@ Here are the results of a few applications of these functions. t ← towerOfHanoi t.View@ ⟨ ⟨ 0 1 2 3 4 ⟩ ⟨⟩ ⟨⟩ ⟩ + t.Move 0‿2 ⟨ ⟨ 1 2 3 4 ⟩ ⟨⟩ ⟨ 0 ⟩ ⟩ + t.Move 1‿2 ! "No disk to move" + t.Move 0‿1 ⟨ ⟨ 2 3 4 ⟩ ⟨ 1 ⟩ ⟨ 0 ⟩ ⟩ + t.Move 2‿1 ⟨ ⟨ 2 3 4 ⟩ ⟨ 0 1 ⟩ ⟨⟩ ⟩ @@ -78,7 +82,7 @@ A stack is a particularly simple class to make because its state can be represen ## Mutability -An object is one way to transform *variable mutation* `↩` into *mutable data*. These are two different concepts: `↩` changes which value is attached to a *name* in a scope, while mutable data means that the behavior of a particular *value* can change. But if a value is linked to a scope (for an object, the scope that contains its fields), then variable mutation in that scope can chang the value's behavior. In fact, in BQN this is the only way to create mutable data. Which doesn't mean it's rare: functions, modifiers, and namespaces are all potentially mutable. The difference between objects and the operations is just a matter of syntax. Mutability in operations can only be observed by calling them. For instance `F 10` or `-_m` could return a different result even if the variables involved don't change value. Mutability in an object can be observed by accessing a member, meaning that `obj.field` or `⟨field⟩←obj` can yield different values over the course of a program even if `obj` is still the same object. +An object is one way to transform *variable mutation* `↩` into *mutable data*. These are two different concepts: `↩` changes which value is attached to a *name* in a scope, while mutable data means that the behavior of a particular *value* can change. But if a value is linked to a scope (for an object, the scope that contains its fields), then variable mutation in that scope can change the value's behavior. In fact, in BQN this is the only way to create mutable data. Which doesn't mean it's rare: functions, modifiers, and namespaces are all potentially mutable. The difference between objects and the operations is just a matter of syntax. Mutability in operations can only be observed by calling them. For instance `F 10` or `-_m` could return a different result even if the variables involved don't change value. Mutability in an object can only be observed by accessing a member, meaning that `obj.field` or `⟨field⟩←obj` can yield different values over the course of a program even if `obj` is still the same object. Let's look at how mutability plays out in an example class for a single-ended queue. This queue works by linking new nodes to the tail `t` of the queue, and detaching nodes from the head `h` when requested (a detached node will still point to `h`, but nothing in the queue points to *it*, so it's unreachable and will eventually be garbage collected). Each node has some data `v` and a single node reference `n` directed tailwards; in a double-ended queue or more complicated structure it would have more references. You can find every mutable variable in the queue by searching for `↩`, which shows that `t` and `h` in the queue, and `n` in a node, may be mutated. It's impossible for the other variables to change value once they're assigned. diff --git a/doc/order.md b/doc/order.md index c9958644..77e3a7c8 100644 --- a/doc/order.md +++ b/doc/order.md @@ -2,7 +2,7 @@ # Ordering functions -BQN has six functions that order arrays as part of their operation (the comparison functions `≤<>≥` only order atoms, so they aren't included). These come in three pairs, where one of each pair uses an ascending ordering and the other uses a descending ordering. +BQN has six functions that order arrays as part of their operation (the [comparison functions](arithmetic.md#comparisons) `≤<>≥` only order atoms, so they aren't included). These come in three pairs, where one of each pair uses an ascending ordering and the other uses a descending ordering. - `∨∧`, Sort, rearranges the argument to order it - `⍒⍋`, Grade, outputs the permutation that Sort would use to rearrange it @@ -20,7 +20,7 @@ You've probably seen it before. Sort Up (`∧`) reorders the major cells of its ∨ "δαβγ" -Sort Down always [matches](match.md) Sort Up reversed, `⌽∘∧`. The reason for this is that BQN's array ordering is a [total order](https://en.wikipedia.org/wiki/Total_order), meaning that if one array doesn't come earlier or later that another array in the ordering then the two arrays match. Since any two non-matching argument cells are strictly ordered, they will have one ordering in `∧` and the opposite ordering in `∨`. With the reverse, any pair of non-matching cells are ordered the same way in `⌽∘∧` and `∨`. Since these two results have the same major cells in the same order, they match. However, note that the results will not always behave identically because Match doesn't take fill elements into account (if you're curious, take a look at `⊑¨∨⟨↕0,""⟩` versus `⊑¨⌽∘∧⟨↕0,""⟩`). +Sort Down always [matches](match.md) Sort Up [reversed](reverse.md), `⌽∘∧`. The reason for this is that BQN's array ordering is a [total order](https://en.wikipedia.org/wiki/Total_order), meaning that if one array doesn't come earlier or later that another array in the ordering then the two arrays match. Since any two non-matching argument cells are strictly ordered, they will have one ordering in `∧` and the opposite ordering in `∨`. With the reverse, any pair of non-matching cells are ordered the same way in `⌽∘∧` and `∨`. Since these two results have the same major cells in the same order, they match. However, note that the results will not always behave identically because Match doesn't take fill elements into account (if you're curious, take a look at `⊑¨∨⟨↕0,""⟩` versus `⊑¨⌽∘∧⟨↕0,""⟩`). ## Grade @@ -74,7 +74,7 @@ To see some of the possibilities of Grade, you might pick apart the following ex The two Bins functions are written with the same symbols `⍋` and `⍒` as Grade, but take two arguments instead of one. More complicated? A little, but once you understand Bins you'll find that it's a basic concept that shows up in the real world all the time. -Bins behaves like a dyadic search function: it looks up cells from the right argument relative to major cells of the left argument. However, there's an extra requirement: the left argument to Bins is already sorted according to whichever ordering is used. If it isn't, you'll get an error. +Bins behaves like a [search function](search.md) with respect to rank: it looks up cells from `𝕩` relative to major cells of `𝕨`. However, there's an extra requirement: the left argument to Bins is already sorted according to whichever ordering is used. If it isn't, you'll get an error. 5‿6‿2‿4‿1 ⍋ 3 0‿3‿4‿7‿9 ⍒ 3 @@ -95,7 +95,7 @@ Most of the time you won't need to worry about the details of how BQN arrays are The array ordering defines some arrays to be smaller or larger than others. All of the "Up" ordering functions use this ordering directly, so that smaller arrays come earlier, and the "Down" ones use the opposite ordering, with larger arrays coming earlier. For arrays consisting only of characters and numbers, with arbitrary nesting, the ordering is always defined. If an array contains an operation, trying to order it relative to another array might give an error. If comparing two arrays succeeds, there are three possibilities: the first array is smaller, the second is smaller, or the two arrays [match](match.md). -Comparing two atoms is defined to work the same way as the comparison functions `≤<>≥`. Numbers come earlier than characters and otherwise these two types are ordered in the obvious way. To compare an atom to an array, the atom enclosing and then compared with the array ordering defined below. The result of this comparison is used except when the two arrays match: in that case, the atom is considered smaller. +Comparing two atoms is defined to work the same way as the [comparison functions](arithmetic.md#comparisons) `≤<>≥`. Numbers come earlier than characters and otherwise these two types are ordered in the obvious way. To compare an atom to an array, the atom enclosing and then compared with the array ordering defined below. The result of this comparison is used except when the two arrays match: in that case, the atom is considered smaller. Two arrays of the same shape are compared by comparing all their corresponding elements, in index order. This comparison can stop at the first pair of different elements (which allows later elements to contain operations without causing an error). If any elements were different, then they decide the result of the comparison. If all the elements matched, then by definition the two arrays match. diff --git a/doc/prefixes.md b/doc/prefixes.md index 41cbd447..0d37e8c8 100644 --- a/doc/prefixes.md +++ b/doc/prefixes.md @@ -7,7 +7,7 @@ The Prefixes (`↑`) function gives a list of all prefixes of its argument array ↑ "abcde" ↓ "abcde" -The functions are closely related to Take and Drop, as we might expect from their glyphs. Element `i⊑↑𝕩` is `i↑𝕩`, and `i⊑↓𝕩` is `i↓𝕩`. +The functions are closely related to [Take and Drop](take.md), as we might expect from their glyphs. Element `i⊑↑𝕩` is `i↑𝕩`, and `i⊑↓𝕩` is `i↓𝕩`. In both cases, an empty array and the entire argument are included in the result, meaning its length is one more than that of the argument. Using [Span](logic.md), we can say that the result has elements whose lengths go from `0` to `≠𝕩`, inclusive, so there are `(≠𝕩)¬0` or `1+≠𝕩` elements. The total number or cells in the result (for example, `≠∾↑𝕩` or `+´≠¨↑𝕩`) scales with the square of the argument length—it is quadratic in `≠𝕩`. We can find the exact total by looking at Prefixes and Suffixes together: @@ -18,7 +18,7 @@ Joining corresponding elements of `↑𝕩` and `↓𝕩` gives `𝕩` again. Th ## Definition -Knowing the length and the elements, it's easy to define functions for Prefixes and Suffixes: `↑` is equivalent to `(↕1+≠)↑¨<` while `↓` is `(↕1+≠)↓¨<`. Each primitive is defined only on arrays with at least one axis. +Knowing the [length](shape.md) and the elements, it's easy to define functions for Prefixes and Suffixes: `↑` is equivalent to `(↕1+≠)↑¨<` while `↓` is `(↕1+≠)↓¨<`. Each primitive is defined only on arrays with at least one axis. ## Working with pairs @@ -26,7 +26,7 @@ Sometimes it's useful to apply an operation to every unordered pair of elements ×⌜˜ 1+↕6 -It's easy enough to use the Table modifier here, but it also computes most products twice. If we only care about the unique products, we could multiply each number by all the ones after it. "After" sounds like suffixes, so let's look at those: +It's easy enough to use the [Table](map.md#table) modifier here, but it also computes most products twice. If we only care about the unique products, we could multiply each number by all the ones after it. "After" sounds like suffixes, so let's look at those: 1+↕6 ↓ 1+↕6 @@ -36,7 +36,7 @@ We want to include the diagonal, so we'll pair each element with the correspondi (⊢ × ≠ ↑ ↓) 1+↕6 (⊢ × 1 ↓ ↓) 1+↕6 -By using `≍` instead of `×`, we can see the argument ordering, demonstrating that we are looking at the upper right half of the matrix produced by Table. While in this case we could use `≍⚇0` to mimic the pervasion of `×`, we'd like this to work even on nested arguments so we should figure out how the mapping structure works to apply Each appropriately. +By using [Couple](couple.md) (`≍`) instead of `×`, we can see the argument ordering, demonstrating that we are looking at the upper right half of the matrix produced by Table. While in this case we could use `≍⚇0` to mimic the pervasion of `×`, we'd like this to work even on nested arguments so we should figure out how the mapping structure works to apply Each appropriately. ≍⌜˜ "abc" (<˘ ≍¨¨ ≠ ↑ ↓) "abc" @@ -54,7 +54,7 @@ Prefixes and Suffixes give certain restricted slices of the argument array, wher ↓¨↑ "abc" ↑¨↓ "abc" -Effectively, this parametrizes the slices either by ending then starting index, or by starting index then length. Four empty slices are included because in a list of length 3 there are 4 places an empty slice can start: all the spaces between or outside elements (these also correspond to all the possible positions for the result of [Bins](bins.md)). The slices can also be parametrized by length and then starting index using [Windows](windows.md). +Effectively, this parametrizes the slices either by ending then starting index, or by starting index then length. Four empty slices are included because in a list of length 3 there are 4 places an empty slice can start: all the spaces between or outside elements (these also correspond to all the possible positions for the result of [Bins](order.md#bins)). The slices can also be parametrized by length and then starting index using [Windows](windows.md). ((↕1+≠)↕¨<) "abc" ((↕1+≠)<˘∘↕¨<) "abc" # Split them to match Prefixes/Suffixes @@ -69,7 +69,7 @@ This array can be [joined](join.md), indicating that the length of each inner ax ∾ 1‿1 ↓ ((↕1+≢)<⎉2∘↕¨<) 3‿2⥊"abcdef" -But Prefixes and Suffixes [don't have](../commentary/problems.md#cant-take-prefixes-or-suffixes-on-multiple-axes) any way to specify that they should work on multiple axes, and always work on exactly one. So to extend this pattern we will have to define multi-dimensional versions. This turns out to be very easy: just replace Length with Shape in the [definitions](#definition) above. +But Prefixes and Suffixes [don't have](../commentary/problems.md#cant-take-prefixes-or-suffixes-on-multiple-axes) any way to specify that they should work on multiple axes, and always work on exactly one. So to extend this pattern we will have to define multi-dimensional versions. This turns out to be very easy: just replace Length with [Shape](shape.md) in the [definitions](#definition) above. Prefs ← (↕1+≢)↑¨< Suffs ← (↕1+≢)↓¨< diff --git a/doc/range.md b/doc/range.md index 846abdc5..60e1afbb 100644 --- a/doc/range.md +++ b/doc/range.md @@ -10,7 +10,7 @@ Range (`↕`) is a monadic function that creates arrays of [indices](indices.md) It's really two different functions packed together: if `𝕩` is a natural number—a length—then it returns a list of numeric indices, but if it's a list of numbers, then it returns an array of list indices. This means the result always has [depth](depth.md) one more than the argument. -The two kinds of index correspond to BQN's two selection functions: Select (`⊏`) works with indices along an axis, which are numbers, and Pick (`⊑`) works with element indices, which are lists. The examples below would fail if we swapped these around. Each result from Range is a length-6 list, but their elements are different. +The two kinds of index correspond to BQN's two selection functions: [Select](select.md) (`⊏`) works with indices along an axis, which are numbers, and [Pick](pick.md) (`⊑`) works with element indices, which are lists. The examples below would fail if we swapped these around. Each result from Range is a length-6 list, but their elements are different. ↕6 @@ -20,7 +20,7 @@ The two kinds of index correspond to BQN's two selection functions: Select (`⊏ (↕⟨6⟩) ⊑ " pick " -They also correspond to Length (`≠`) and Shape (`≢`): for an array `a`, `↕≠a` gives the indices of major cells, while `↕≢a` gives the indices of all elements. +They also correspond to Length (`≠`) and [Shape](shape.md) (`≢`): for an array `a`, `↕≠a` gives the indices of major cells, while `↕≢a` gives the indices of all elements. a ← 4‿2⥊@ @@ -62,7 +62,7 @@ One interesting use of Range is to find, at each position in a boolean list, the b × ↕≠b -Now at any given position the index of the last 1, if there is any, is the maximum of all the adjusted indices so far. That's a scan `` ⌈` ``. +Now at any given position the index of the last 1, if there is any, is the [maximum](arithmetic.md#additional-arithmetic) of all the adjusted indices so far. That's a [scan](scan.md) `` ⌈` ``. ⌈` b × ↕≠b diff --git a/doc/replicate.md b/doc/replicate.md index 780f5654..29ecbaae 100644 --- a/doc/replicate.md +++ b/doc/replicate.md @@ -83,7 +83,7 @@ Here the `2‿0` indicates that the first row of `b` is copied twice and the sec ⟨<2,<3⟩ / b -Above, both elements of `𝕨` are enclosed numbers. An individual element doesn't have to be enclosed, but I don't recommend this, since if *none* of them are enclosed, then `𝕨` will have depth 1 and it will be interpreted as replicating along the first axis only. +Above, both elements of `𝕨` are [enclosed](enclose.md) numbers. An individual element doesn't have to be enclosed, but I don't recommend this, since if *none* of them are enclosed, then `𝕨` will have depth 1 and it will be interpreted as replicating along the first axis only. ⟨2,3⟩ / b @@ -95,7 +95,7 @@ If `𝕨` is `⟨⟩`, then it has depth 1, but is handled with the multidimensi ## Indices -The monadic form of `/` is much simpler than the dyadic one, with no multidimensional case or mismatched argument ranks. `𝕩` must be a list of natural numbers, and `/𝕩` is the list `𝕩/↕≠𝕩`. Its elements are the indices for `𝕩`, with index `i` repeated `i⊑𝕩` times. +The monadic form of `/` is much simpler than the dyadic one, with no multidimensional case or mismatched argument ranks. `𝕩` must be a list of natural numbers, and `/𝕩` is the list `𝕩/↕≠𝕩`. Its elements are the [indices](indices.md) for `𝕩`, with index `i` repeated `i⊑𝕩` times. / 3‿0‿1‿2 @@ -107,13 +107,13 @@ When `𝕨` has rank 1, `𝕨/𝕩` is equivalent to `𝕨/⊸⊏𝕩`. Of cours This function will fail to include trailing empty arrays; the modification `(/∾⟜1)⊸⊔` fixes this and ensures the result always has as many elements as `𝕨`. -If `𝕩` is boolean then `/𝕩` contains all the indices where a 1 appears in `𝕩`. Applying `-⟜»` to the result gives the distance from each 1 to the previous, or to the start of the list, another potentially useful function. +If `𝕩` is boolean then `/𝕩` contains all the indices where a 1 appears in `𝕩`. Applying `-⟜»` to the result gives the distance from each 1 to the [previous](shift.md), or to the start of the list, another potentially useful function. / 0‿1‿0‿1‿0‿0‿0‿0‿1‿0 -⟜» / 0‿1‿0‿1‿0‿0‿0‿0‿1‿0 -With more effort we can also use `/` to analyze groups of 1s in the argument (and of course all these methods can be applied to 0s instead, by first flipping the values with `¬`). First we highlight the start and end of each group by comparing the list with a shifted copy of itself. Or rather, we'll first place a 0 at the front and then at the end, in order to detect when a group starts at the beginning of the list or ends at the end (there's also a [shift](shift.md)-based version, `≠⟜«0∾𝕩`). +With more effort we can also use `/` to analyze groups of 1s in the argument (and of course all these methods can be applied to 0s instead, by first flipping the values with `¬`). First we highlight the start and end of each group by comparing the list with a shifted copy of itself. Or rather, we'll first place a 0 at the front and then at the end, in order to detect when a group starts at the beginning of the list or ends at the end (there's also a shift-based version, `≠⟜«0∾𝕩`). 0 (∾≍∾˜) 0‿1‿1‿1‿0‿0‿1‿0‿1‿1‿0 |
