From 8342ba5e9392811dbc0514a97e847a44a5b330a2 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 6 Jun 2022 21:29:06 -0400 Subject: When I wrote all these docs did I really understand I'd have to edit them? --- docs/doc/glossary.html | 1 + docs/doc/prefixes.html | 46 ++++++++++++++++++++++++++++------------------ docs/doc/primitive.html | 34 +++++++++++++++++----------------- docs/doc/range.html | 14 +++++++------- docs/doc/repeat.html | 8 ++++---- docs/doc/replicate.html | 8 ++++---- docs/doc/reshape.html | 18 +++++++++--------- docs/doc/reverse.html | 16 ++++++++-------- 8 files changed, 78 insertions(+), 67 deletions(-) (limited to 'docs/doc') diff --git a/docs/doc/glossary.html b/docs/doc/glossary.html index 16a1ade3..1bd32484 100644 --- a/docs/doc/glossary.html +++ b/docs/doc/glossary.html @@ -76,6 +76,7 @@

Operations

diff --git a/docs/doc/prefixes.html b/docs/doc/prefixes.html index dd27b18c..1147dc51 100644 --- a/docs/doc/prefixes.html +++ b/docs/doc/prefixes.html @@ -5,15 +5,16 @@

Prefixes and Suffixes

-

The Prefixes () function gives a list of all prefixes of its argument array along the first axis, and Suffixes () gives a similar list for suffixes. Because the result can be much larger than the argument, these functions may not be used often in high-performance code, but they are a powerful conceptual tool and can make sense for algorithms that are inherently quadratic.

-↗️
     "abcde"
+

The Prefixes () function gives a list of all prefixes of its argument array along the first axis, and Suffixes () gives a similar list for suffixes. Because the result can be much larger than the argument, these functions may not be used often in high-performance code, but they are a good conceptual tool and can make sense for algorithms that are inherently quadratic.

+↗️
     "abcde"
 ⟨ ⟨⟩ "a" "ab" "abc" "abcd" "abcde" ⟩
+
      "abcde"
 ⟨ "abcde" "bcde" "cde" "de" "e" ⟨⟩ ⟩
 

The functions are closely related to Take and Drop, 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, 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:

-↗️
    ( ˘ ) "abcde"
+

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, 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 of cells in the result (for example, ≠∾↑𝕩 or +´¨𝕩) scales with the square of the argument length—it's quadratic in 𝕩. We can find the exact total by looking at Prefixes and Suffixes together:

+↗️
    ( ˘ ) "abcde"
 ┌─                 
 ╵ ⟨⟩      "abcde"  
   "a"     "bcde"   
@@ -22,12 +23,14 @@
   "abcd"  "e"      
   "abcde" ⟨⟩       
                   ┘
+
     ( ¨ ) "abcde"
 ⟨ "abcde" "abcde" "abcde" "abcde" "abcde" "abcde" ⟩
 
-

Joining corresponding elements of 𝕩 and 𝕩 gives 𝕩 again. This is because i(↑∾¨)𝕩 is (i⊑↑𝕩)(i⊑↓𝕩), or, using the Take and Drop correspondences, (i𝕩)(i𝕩), which is 𝕩. Element-wise, we are combining the first i cells of 𝕩 with all but the first i. Looking at the entire result, we now know that (↑∾¨)𝕩 is (1+≠𝕩)⥊<𝕩. The total number of cells in this combined array is therefore (1+≠𝕩)×≠𝕩, or 1+×≠𝕩. Each of Prefixes and Suffixes must have the same total number of cells (in fact, 𝕩 is ¨𝕩, and Reverse doesn't change an array's shape). So the total number in either one is 2÷˜1+×≠𝕩. With n𝕩, it is 2÷˜n×1+n.

+

Joining corresponding elements of 𝕩 and 𝕩 gives 𝕩 again. This is because i(↑∾¨)𝕩 is (i⊑↑𝕩)(i⊑↓𝕩), or, using the Take and Drop correspondences, (i𝕩)(i𝕩), which is 𝕩. Element-wise, we are combining the first i cells of 𝕩 with all but the first i.

+

Looking at the entire result, we now know that (↑∾¨)𝕩 is (1+≠𝕩)⥊<𝕩. The total number of cells in this combined array is therefore (1+n)×n, setting n𝕩. Each of Prefixes and Suffixes must have the same total number of cells (in code, 𝕩 is ¨𝕩, and Reverse doesn't change an array's shape). So the total number in either one is 2÷˜n×1+n.

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 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

Sometimes it's useful to apply an operation to every unordered pair of elements from a list. For example, consider all possible products of numbers between 1 and 6:

↗️
    ×⌜˜ 1+↕6
@@ -41,48 +44,54 @@
                    ┘
 

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:

-↗️
    1+↕6
+↗️
    1+↕6
 ⟨ 1 2 3 4 5 6 ⟩
+
      1+↕6
 ⟨ ⟨ 1 2 3 4 5 6 ⟩ ⟨ 2 3 4 5 6 ⟩ ⟨ 3 4 5 6 ⟩ ⟨ 4 5 6 ⟩ ⟨ 5 6 ⟩ ⟨ 6 ⟩ ⟨⟩ ⟩
 

We want to include the diagonal, so we'll pair each element with the corresponding element of the suffixes, reducing the suffixes to the original array's length by dropping the last element, which is empty. In other cases, we might not want to include it and we should instead drop the first element.

-↗️
    ( ×   ) 1+↕6
+↗️
    ( ×   ) 1+↕6
 ⟨ ⟨ 1 2 3 4 5 6 ⟩ ⟨ 4 6 8 10 12 ⟩ ⟨ 9 12 15 18 ⟩ ⟨ 16 20 24 ⟩ ⟨ 25 30 ⟩ ⟨ 36 ⟩ ⟩
+
     ( × 1  ) 1+↕6
 ⟨ ⟨ 2 3 4 5 6 ⟩ ⟨ 6 8 10 12 ⟩ ⟨ 12 15 18 ⟩ ⟨ 20 24 ⟩ ⟨ 30 ⟩ ⟨⟩ ⟩
 
-

By using Couple () 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"
+

By using Pair () 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"
 ┌─                
 ╵ "aa" "ab" "ac"  
   "ba" "bb" "bc"  
   "ca" "cb" "cc"  
                  ┘
-    (<˘ ¨¨   ) "abc"
+
+    (<˘ ¨¨   ) "abc"
 ⟨ ⟨ "aa" "ab" "ac" ⟩ ⟨ "bb" "bc" ⟩ ⟨ "cc" ⟩ ⟩
 
-

As before, we can exclude the diagonal, and using Prefixes instead of Suffixes gives us the lower left half instead of the upper right—in terms of the arguments given to it reverses the argument pairs and iterates in a different order.

-↗️
    (<˘ ¨¨ 1  ) "abc"
+

As before, we can exclude the diagonal, and using Prefixes instead of Suffixes gives us the lower left half instead of the upper right—in terms of the arguments given to it reverses the argument pairs and iterates in a different order.

+↗️
    (<˘ ¨¨ 1  ) "abc"
 ⟨ ⟨ "ab" "ac" ⟩ ⟨ "bc" ⟩ ⟨⟩ ⟩
-    (<˘ ¨¨ 1  ) "abc"
+
+    (<˘ ¨¨ 1  ) "abc"
 ⟨ ⟨ "aa" ⟩ ⟨ "ba" "bb" ⟩ ⟨ "ca" "cb" "cc" ⟩ ⟩
-    (<˘ ¨¨   ) "abc"
+
+    (<˘ ¨¨   ) "abc"
 ⟨ ⟨⟩ ⟨ "ba" ⟩ ⟨ "ca" "cb" ⟩ ⟩
 

Slices

-

Prefixes and Suffixes give certain restricted slices of the argument array, where a slice is a contiguous selection of cells. If we want all slices along the first axis, we can take the suffixes of each prefix, or vice-versa:

-↗️
    ¨ "abc"
+

Prefixes and Suffixes give certain restricted slices of the argument array, where a slice is a contiguous selection of major cells. If we want all slices along the first axis, we can take the suffixes of each prefix, or vice-versa:

+↗️
    ¨ "abc"
 ┌─                                                         
 · ⟨ ⟨⟩ ⟩ ⟨ "a" ⟨⟩ ⟩ ⟨ "ab" "b" ⟨⟩ ⟩ ⟨ "abc" "bc" "c" ⟨⟩ ⟩  
                                                           ┘
+
     ¨ "abc"
 ┌─                                                         
 · ⟨ ⟨⟩ "a" "ab" "abc" ⟩ ⟨ ⟨⟩ "b" "bc" ⟩ ⟨ ⟨⟩ "c" ⟩ ⟨ ⟨⟩ ⟩  
                                                           ┘
 

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). The slices can also be parametrized by length and then starting index using Windows.

-↗️
    ((1+≠)¨<) "abc"
+↗️
    ((1+≠)¨<) "abc"
 ┌─                         
 · ┌┐ ┌─    ┌─     ┌─       
   ╵  ╵"a   ╵"ab   ╵"abc"   
@@ -91,6 +100,7 @@
          ┘                 
    ┘                       
                           ┘
+
     ((1+≠)<˘¨<) "abc"  # Split them to match Prefixes/Suffixes
 ┌─                                                         
 · ⟨ ⟨⟩ ⟨⟩ ⟨⟩ ⟨⟩ ⟩ ⟨ "a" "b" "c" ⟩ ⟨ "ab" "bc" ⟩ ⟨ "abc" ⟩  
diff --git a/docs/doc/primitive.html b/docs/doc/primitive.html
index 3da3019b..a981ae81 100644
--- a/docs/doc/primitive.html
+++ b/docs/doc/primitive.html
@@ -5,8 +5,8 @@
 
 
 

BQN primitives

-

Primitives are the basic functions and modifiers built into the language, written with individual glyphs (more about the concept here). The role of a primitive when written always matches its type (but you can use its value in other roles by assigning it, or other methods).

-

Primitives have no side effects other than errors, and can't perform infinite computations, except when a primitive modifier calls an operand function that does one of these things (this can only happen when arguments are passed, as primitive modifiers are always deferred). Side effects here include both writing state such as variables or printed output, and reading any outside state, so that a function without them always returns the same result if passed the same arguments. Since trains and list notation have the same nice properties, tacit code written entirely with primitives, trains, and lists always describes finite, self-contained computations.

+

Primitives are the basic functions and modifiers built into the language, written with individual glyphs (more about the concept here). The role of a primitive when written always matches its type (but you can use its value in other roles by assigning it, or other methods).

+

Primitives have no side effects other than errors, and can't perform infinite computations, except when a primitive modifier calls an operand function that does one of these things (and this can only happen when arguments are passed, as primitive modifiers are always deferred). Side effects here include both writing state such as variables or printed output, and reading any outside state, so that a function without them always returns the same result if passed the same arguments. Since trains and list notation have the same nice properties, tacit code written entirely with primitives, trains, and lists always describes finite, self-contained computations.

Recursion is the primary way to perform potentially infinite computations in BQN, and it can be packaged into control structures like While for ease of use. A given BQN implementation might also provide system values for "impure" tasks like file access or other I/O.

Functions

A function call with one argument (prefix) is called "monadic" and one with two arguments (infix) is "dyadic".

@@ -412,7 +412,7 @@ -

Combinators only control the application of functions. Because a non-function operand applies as a constant function, some combinators have extra meanings when passed a constant. For example, 0˜ is identical to 0˙—a constant function that always returns 0—and 0< is the function that tests whether its right argument is greater than 0.

+

Combinators only control the application of functions, which are passed as operands. A data value such as a number or array can also be an operand and, as always, applies as a constant function.

@@ -460,12 +460,6 @@ - - - - - - @@ -477,10 +471,22 @@ + + + + + + + + + + + +
𝔽's right argument comes from 𝔾
Under{𝔾𝔽𝔾} OR {(𝔾𝕩)𝕨𝔽𝔾𝕩𝕩}Apply 𝔽 over 𝔾, then undo 𝔾
Valences {𝔽𝕩;𝕨𝔾𝕩}{f(𝕨𝔽𝕩)𝕘 𝕨F𝕩} Select one of the functions in list 𝕘 based on 𝔽
Under{𝔾𝔽𝔾} OR {(𝔾𝕩)𝕨𝔽𝔾𝕩𝕩}Apply 𝔽 over 𝔾, then undo 𝔾
Catch{𝕨𝔽𝕩… 𝕨𝔾𝕩}Apply 𝔽, but if it fails catch the error and apply 𝔾
-

Choose isn't really a combinator since it calls the function , and Under is not a true combinator since it has an "undo" step at the end. This step might be implemented using the left operand's inverse (computational Under) or its structural properties (structural Under).

-

Other modifiers control array traversal and iteration. In three cases a simpler 1-modifier is paired with a generalized 2-modifier: in each case the 1-modifier happens to be the same as the 2-modifier with a right operand of ¯1.

+

The last three are combinators in spirit but go beyond the actual strict definition: Choose calls the function , Under has an "undo" step at the end, and Catch traps an error. The second definition for Under and the one for Catch are written in pseudo-BQN because they can't be expressed otherwise.

+

Other modifiers control array traversal and iteration. In three cases a simpler 1-modifier is paired with a generalized 2-modifier: for each of these the 1-modifier happens to be the same as the 2-modifier with a right operand of ¯1.

@@ -533,11 +539,5 @@ - - - - - -
Catch
diff --git a/docs/doc/range.html b/docs/doc/range.html index 8065a34a..887f9833 100644 --- a/docs/doc/range.html +++ b/docs/doc/range.html @@ -5,7 +5,7 @@

Range

-

Range () is a monadic function that creates arrays of indices (like APL's famous iota function). Each element in the result is its own index.

+

Range () is a monadic function that creates arrays of indices, like APL's famous iota function . Each element in the result is its own index.

↗️
     6
 ⟨ 0 1 2 3 4 5 ⟩
 
@@ -29,7 +29,7 @@
     (6)  " pick "
 " 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 (): for an array a, ↕≠a gives the indices of major cells, while ↕≢a gives the indices of all elements.

↗️
    a  42@
 
       a
@@ -54,11 +54,11 @@
     2  4
 ⟨ 2 3 ⟩
 
-

The result of 𝕩 is a list of length 𝕩, but doesn't include 𝕩 itself. That's just how counting starting at 0 works. It does mean we can create a length-0 list easily:

+

The result of 𝕩 is a list of length 𝕩, but doesn't include 𝕩 itself. That's just how counting starting at 0 works (but a nice trick if you do want to include 𝕩 is 𝕩). It means we can create a length-0 list easily:

↗️
     0
 ⟨⟩
 
-

Like all other results of on a number, 0 has a fill of 0.

+

As with any other number argument, 0 has a fill of 0.

↗️
    4  0
 ⟨ 0 0 0 0 ⟩
 
@@ -72,7 +72,7 @@
     »3 'b'+↕8
 "   bcdef"
 
-

One interesting use of Range is to find, at each position in a boolean list, the most recent index that has a 1. To do this, first get the array of indices for b, ↕≠b. Then multiply b, reducing indices where a 0 is found to 0.

+

One interesting use of Range is to find, at each position in a boolean list, the most recent index that has a 1. To do this, first get the array of indices for b, ↕≠b. Then multiply by b, reducing indices where a 0 is found to 0.

↗️
     b  01100010
 ⟨ 0 1 1 0 0 0 1 0 ⟩
 
@@ -97,7 +97,7 @@
 ⟨ 0 2 3 3 3 3 7 7 ⟩
 

List range

-

When the argument is a list of numbers, the result is an array of lists.

+

When 𝕩 is a list of numbers, the result is an array of lists.

↗️
     234
 ┌─                                         
 ╎ ⟨ 0 0 0 ⟩ ⟨ 0 0 1 ⟩ ⟨ 0 0 2 ⟩ ⟨ 0 0 3 ⟩  
@@ -109,7 +109,7 @@
   ⟨ 1 2 0 ⟩ ⟨ 1 2 1 ⟩ ⟨ 1 2 2 ⟩ ⟨ 1 2 3 ⟩  
                                           ┘
 
-

This array, which contains all possible choices of one natural number less than each element of 𝕩, can also be produced using Range on numbers only, along with Table ().

+

This array, which contains all possible choices of a natural number below each element of 𝕩, can also be produced using Range on numbers only, along with Table ().

↗️
    (<⟨⟩) ⌜´ ¨ 234
 ┌─                                         
 ╎ ⟨ 0 0 0 ⟩ ⟨ 0 0 1 ⟩ ⟨ 0 0 2 ⟩ ⟨ 0 0 3 ⟩  
diff --git a/docs/doc/repeat.html b/docs/doc/repeat.html
index b5e4ba06..bf097430 100644
--- a/docs/doc/repeat.html
+++ b/docs/doc/repeat.html
@@ -12,7 +12,7 @@
     »3 "ABCDE"
 "   AB"
 
-

In mathematics (which unsurpisingly tends to use complicated terms to talk about an easy concept), this kind of repetition is called an iterated function and written with exponential notation. It's related to function composition in the same way that exponentiation () relates to multiplication (×): function iteration is repeated composition.

+

In mathematics (which unsurpisingly tends to use complicated terms to talk about an easy concept), this kind of repetition is called an iterated function and written with exponential notation. It's related to function composition in the same way that exponentiation () relates to multiplication (×): function iteration is repeated composition.

n4  ←→  n×n×n×n
 F4  ←→  FFFF
 
@@ -25,7 +25,7 @@ 3 + 3 + 7 13
-

This kind of composition can't be represented by anymore (you'd need a train), but it's similar in spirit. 𝕨 𝔽n 𝕩 is always equivalent to 𝕨𝔽n 𝕩, provided n is a constant—not a function, as discussed in the next section.

+

This kind of composition can't be represented by anymore (you'd need a train), but it's not much of a leap. 𝕨 𝔽n 𝕩 is always equivalent to 𝕨𝔽n 𝕩, provided n is a constant—not a function, as discussed in the next section.

Dynamic repetition count

In the general case, 𝔾 is a function, which is applied to all arguments to get the repetition count. That is, the actual count is 𝕨𝔾𝕩.

↗️
    1 4
@@ -43,11 +43,11 @@
 ⟨ 2 3 3 ⟩
 

Negative repetition

-

What does it mean to repeat a function a negative number of times? For a negative integer -n, BQN defines F(-n) to be Fn. In particular, F¯1 simply undoes F.

+

What does it mean to repeat a function a negative number of times? For a negative integer -n, BQN defines F(-n) to be Fn. In particular, F¯1 simply undoes F.

↗️
    1 ¯1 "abcde"  # Rotate backwards
 "eabcd"
 
-

Because BQN's Undo is a little looser than a strict mathematical inverse, this is an extension of the function inverse written f⁻¹ in mathematics. As a result, it doesn't have all the same properties. For natural numbers, Repeat follows the rule that Fm Fn 𝕩 is F(m+n) 𝕩. For integers, we have 𝕩 Fn F(-n) 𝕩, but not necessarily 𝕩 F(-n) Fn 𝕩.

+

Because BQN's Undo is a little looser than a strict mathematical inverse, this is an extension of the function inverse written f⁻¹ in mathematics. As a result, it doesn't have all the same properties. For natural numbers, Repeat follows the rule that Fm Fn 𝕩 is F(m+n) 𝕩. With a negative, we have 𝕩 Fn F(-n) 𝕩, but not necessarily 𝕩 F(-n) Fn 𝕩.

Array of repetition counts

The value of 𝕨𝔾𝕩 might also be an array, whose elements are any valid repetition values—integers, or other arrays. Each integer in the nested structure is replaced with the result of repeating 𝔽 that many times.

↗️
    2×2,4,¯2,1⟩⟩ 1
diff --git a/docs/doc/replicate.html b/docs/doc/replicate.html
index 31e63228..4387373b 100644
--- a/docs/doc/replicate.html
+++ b/docs/doc/replicate.html
@@ -88,7 +88,7 @@
 

The functions Indices and Replicate are used to copy or filter data. They might be described as transforming a run-length encoding into unencoded form. On the other hand, Indices might be described as giving a sparse representation of 𝕩, which is smaller if 𝕩 mostly consists of zeros.

BQN doesn't have any of the various features used in APL to add fills to the result of Replicate, like negative numbers in 𝕨 or an Expand (\) primitive. An alternative to Expand is to use Replicate with structural Under () to insert values into an array of fills.

Replicate

-

Given a list of natural numbers 𝕨, Replicate repeats each major cell in 𝕩 the corresponding number of times. That is, 𝕨 and 𝕩 must have the same length, and the result includes i𝕨 copies of each cell i𝕩, in order.

+

Given a list of natural numbers 𝕨, Replicate repeats each major cell in 𝕩 the corresponding number of times. That is, 𝕨 and 𝕩 must have the same length, and the result includes i𝕨 copies of each cell i𝕩, in order.

↗️
    2102 / "abcd"
 "aabdd"
 
@@ -124,7 +124,7 @@
 "fie"
 

Here 'i' is a pervasive function, so there's no need to add ¨. Similarly, to filter major cells of an array, Fn˘/ could be used, applying Fn to one major cell at a time.

-

A similar pattern applies to Replicate as well. The function below tests which input characters are double quotes, but by adding one it changes the result to 1 for each non-quote character and 2 for quotes (but source code and display also double quotes here, so the input string has only two "s and the output has four).

+

This idea extends to Replicate as well. The function below tests which input characters are double quotes, but by adding one it changes the result to 1 for each non-quote character and 2 for quotes (but source code and display also double quotes here, so the input string has only two "s and the output has four).

↗️
    {1+'"'=𝕩}/ "for ""escaping"" quotes"
 "for """"escaping"""" quotes"
 
@@ -173,7 +173,7 @@ 1

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. 𝕩 has to be a list of natural numbers, and /𝕩 is the list 𝕩/↕≠𝕩. Its elements are the indices for 𝕩, with index i repeated i𝕩 times.

↗️
    / 3012
 ⟨ 0 0 0 2 3 3 ⟩
 
@@ -211,7 +211,7 @@ 8 2 ┘
-

This means the transitions can be grouped exactly in pairs, the beginning and end of each group. Reshape with a computed length 2 groups these pairs, and then a scan -˜`˘ can be used to convert the start/end format to start/length if wanted.

+

This means the transitions can be grouped exactly in pairs, the beginning and end of each group. Reshape with a computed length 2 groups these pairs, and then a scan -˜`˘ can be used to convert the start/end format to start/length if wanted.

Inverse

The result of Indices /n is an ordered list of natural numbers, where the number i appears in times. Given an ordered list of natural numbers k, the inverse of indices returns a corresponding n: one where the value in is the number of times i appears in k.

↗️
    / 321
diff --git a/docs/doc/reshape.html b/docs/doc/reshape.html
index 963d03a3..68537bf0 100644
--- a/docs/doc/reshape.html
+++ b/docs/doc/reshape.html
@@ -58,8 +58,8 @@
   
 
 
-

The glyph indicates BQN's facilities to reflow the data in an array, giving it a different shape. Its monadic form, Deshape, simply removes all shape information, returning a list of all the elements from the array in reading order. With a left argument, is called Reshape and is a more versatile tool for rearranging the data in an array into the desired shape.

-

Because of its dependence on the reading order of an array, Reshape is less fundamental than other array operations. Using Reshape in the central computations of a program can be a sign of imperfect usage of arrays. For example, it may be useful to use Reshape to create a constant array or repeat a sequence of values several times, but the same task might also be accomplished more simply with Table , or by taking advantage of leading axis agreement in arithmetic primitives.

+

The glyph indicates BQN's facilities to reflow the data in an array, giving it a different shape. Its monadic form, Deshape, simply removes all shape information, returning a list of all the elements from the array in index order. With a left argument, is called Reshape and is a more versatile tool for rearranging the data in an array into the desired shape.

+

Because of its dependence on the index order of an array, Reshape is less fundamental than other array operations. Using Reshape in the central computations of a program can be a sign of imperfect usage of arrays. For example, it may be useful to use Reshape to create a constant array or repeat a sequence of values several times, but the same task might also be accomplished more simply with Table , or by taking advantage of leading axis agreement in arithmetic primitives.

Deshape

The result of Deshape is a list containing the same elements as the argument.

↗️
     a  +⌜´ 100200, 3040, 567
@@ -74,7 +74,7 @@
      a
 ⟨ 135 136 137 145 146 147 235 236 237 245 246 247 ⟩
 
-

The elements are ordered in reading order—left to right, then top to bottom. This means that leading axes "matter more" for ordering: if one element comes earlier in the first axis but later in the second than some other element, it will come first in the result. In another view, elements are ordered according to their indices. In other words, deshaping the array of indices for an array will always give a sorted array.

+

The elements are ordered in reading order—left to right, then top to bottom. This means that leading axes "matter more" for ordering: if one element comes earlier in the first axis but later in the second than some other element, it will come first in the result. In another view, elements are ordered according to their indices, leading to the name index order for this ordering. To be precise, deshaping the array of indices for an array always gives a sorted array.

↗️
    ↕≢a
 ┌─                               
 ╎ ⟨ 0 0 0 ⟩ ⟨ 0 0 1 ⟩ ⟨ 0 0 2 ⟩  
@@ -87,8 +87,8 @@
       ↕≢a
 ⟨ 0 1 2 3 4 5 6 7 8 9 10 11 ⟩
 
-

This ordering is also known as row-major order.

-

Deshape turns a unit argument into a single-element list, automatically enclosing it if it's an atom. However, if you know 𝕩 is a unit, a more principled way to turn it into a list is to apply Solo (), which adds a length-1 axis before any other axes. If you ever add axes to the data format, Solo is more likely to continue working after this transition, unless there's a reason the result should always be a list.

+

This ordering is also known as row-major order in computing.

+

Deshape turns a unit argument into a single-element list, automatically enclosing it if it's an atom. However, if you know 𝕩 is a unit, a more principled way to turn it into a list is to apply Solo (), which adds a length-1 axis before any other axes. If you ever add axes to the data format, Solo is more likely to continue working after this transition, unless there's a reason the result should always be a list.

↗️
     2
 ⟨ 2 ⟩
      2
@@ -121,7 +121,7 @@
     (a)   62a
 1
 
-

One common use is to generate an array with a specified shape that counts up from 0 in reading order, a reshaped Range. The idiomatic phrase to do this is (↕×´), since it doesn't require writing the shape and its product separately.

+

One use is to generate an array with a specified shape that counts up from 0 in index order, a reshaped Range. The idiomatic phrase to do this is (↕×´), since it doesn't require writing the shape and its product separately.

↗️
    27  14
 ┌─                   
 ╵ 0 1 2  3  4  5  6  
@@ -171,12 +171,12 @@
   uU" 
      ┘
 
-

Above, the length given is , a special value that indicates that a length that fits the argument should be computed. In fact, Reshape has four different special values that can be used. Every one works the same for a case like the one above, where the rest of the shape divides the argument length evenly. They differ in how they handle uneven cases, where the required length would fall between two whole numbers.

+

Above, the length given is , a special value that indicates that a length fitting the argument should be computed. Reshape has four such special values that can be used. Every one works the same for a case like the one above, where the rest of the shape divides the argument length evenly. They differ in how they handle uneven cases, where the required length falls between two whole numbers.

  • says the length must be an exact fit, and gives an error in such a case.
  • rounds the length down, so that some elements are discarded.
  • rounds the length up, repeating elements to make up the difference.
  • -
  • rounds the length up, but uses the argument's fill for the needed extra elements.
  • +
  • rounds the length up, but uses the argument's fill for the needed extra elements.

These values are just BQN primitives of course. They're not called by Reshape or anything like that; the primitives are just chosen to suggest the corresponding functionality.

Here's an example of the four cases. If we try to turn five elements into two rows, gives an error, drops the last element, uses the first element again, and uses a fill element (like 6"abcde" would).

@@ -201,7 +201,7 @@ de " ┘
-

A computed length can be useful to input an array without using nested notation: for example, if you have a table with rows of three elements, you might write it as one long list, using 3 to get it back to the appropriate shape. is definitely the value to use here, as it will check that you haven't missed an element or something like that.

+

A computed length can be useful to input an array without using nested notation: for example, if you have a table with rows of three elements, you might write it as one long list, using 3 to get it back to the appropriate shape. is definitely the value to use here, as it will check that you haven't missed or added an element.

Computed Reshape might also be used in actual data processing: for example, to sum a list in groups of four, you might first reshape it using 4 for the shape, then average the rows. Here the code is useful because added fill elements of 0 won't change the sum, so that if the last group doesn't have four elements (97 below), it will still be summed correctly.

↗️
    +´˘ 4  0,2,1,1, 5,9,6,4, 3,3,3,3, 9,7
 ⟨ 4 24 12 16 ⟩
diff --git a/docs/doc/reverse.html b/docs/doc/reverse.html
index c90f22f2..cd984689 100644
--- a/docs/doc/reverse.html
+++ b/docs/doc/reverse.html
@@ -5,10 +5,10 @@
 
 
 

Reverse and Rotate

-

The symbol indicates two different array transformations: with no left argument, it reverses the major cells of the array, but with a left argument, it rotates or cycles them around. These two possibilities, first put together in very early versions of APL, can't be considered restrictions or different views of some unifying function, but there are connections between them. Each returns an array with the same shape and all the same elements as 𝕩, possibly in a different arrangement. And elements that start out next to each other in 𝕩 generally stay next to each other—always, if we consider an element on one edge to be next to the one opposite to it. One might think of them as isometries preserving a discrete subgroup of the torus, if one were inclined to think such things. On major cells, the two functions decompose the dihedral group okay I'll stop.

-

Many uses of Rotate in APL are better handled by shift functions in BQN. If there's no reason to treat the data as cyclic or periodic, it's best to avoid Rotate.

+

The symbol indicates two different array transformations: with no left argument, it reverses the major cells of the array, but with a left argument, it rotates or cycles them around. These two possibilities, first put together in very early versions of APL, can't be considered restrictions or different views of some unifying function, but there are connections between them. Each returns an array with the same shape and all the same elements as 𝕩, possibly in a different arrangement. And elements that start out next to each other in 𝕩 generally stay next to each other—always, if we consider an element on one edge to be next to the one opposite to it. One might think of them as isometries preserving a discrete subgroup of the torus, if one were inclined to think such things. On major cells, the two functions decompose the dihedral group okay I'll stop.

+

If there's no reason the data should be seen as cyclic or periodic, it's best to avoid Rotate: shift functions are probably more appropriate.

Reverse

-

There's not too much to say about Reverse. It puts the elements of a list the other way around, or more generally the major cells of an array.

+

Reverse doesn't make things complicated. It puts the elements of a list the other way around, or more generally the major cells of an array.

↗️
     "abcdefg"
 "gfedcba"
 
@@ -23,7 +23,7 @@
 Error: ⌽: Argument cannot be a unit
 

You can't reverse an atom or rank-0 array because it has no axes to reverse along, or it could be said no ordering to reverse.

-

To reverse along an axis other than the first, use Cells (˘) or Rank ().

+

To reverse along an axis other than the first, use Cells (˘) or Rank ().

↗️
    ˘ >"ab""cd""ef"
 ┌─    
 ╵"ba  
@@ -38,7 +38,7 @@
     ˜´  "abcd"  # Left to right
 ⟨ ⟨ "ab" 'c' ⟩ 'd' ⟩
 
-

Reverse is its own inverse . As a result, 𝔽 reverses the argument, applies 𝔽, and reverses again. It's a particularly useful pattern with Scan, as it allows scanning from the end rather than the beginning of the array. For example, ` on a list of booleans changes all bits after the first 1 to 1, but ` does this to all bits before the last 1.

+

Reverse is its own inverse . So with Under, 𝔽 reverses the argument, applies 𝔽, and reverses again. It's a particularly useful pattern with Scan, as it allows scanning from the end rather than the beginning of the array. For example, ` on a list of booleans changes all bits after the first 1 to 1, but ` does this to all bits before the last 1.

↗️
    `   0010010
 ⟨ 0 0 1 1 1 1 1 ⟩
 
@@ -74,7 +74,7 @@
 "terota"
 

Multiple axes

-

The easiest way to rotate a later array axis is usually to use the Cells (˘) or Rank () modifier.

+

The easiest way to rotate along a later array axis is usually to use the Cells (˘) or Rank () modifier.

↗️
     tab  34"abcdABCD0123"
 ┌─      
 ╵"abcd  
@@ -89,7 +89,7 @@
   1230" 
        ┘
 
-

Rotate also allows 𝕨 to be a list (or unit array) of integers, in which case they're matched with leading axes of 𝕩. This means the length of 𝕨 can't be larger than the rank of 𝕩, or there wouldn't be enough axes to match. This rule also explains why 𝕩 has to have rank one or more when 𝕨 is an atom, because 𝕨 is treated as the one-element list 𝕨 in that case.

+

Rotate also allows 𝕨 to be a list (or unit array) of integers, in which case they're matched with leading axes of 𝕩. This means the length of 𝕨 can't be larger than the rank of 𝕩, or there wouldn't be enough axes to match. This rule that 𝕩 has to have rank one or more when 𝕨 is an atom is a special case, because then 𝕨 is treated as the one-element list 𝕨.

↗️
    342  "just a list"
 Error: 𝕨⌽𝕩: Length of compound 𝕨 must be at most rank of 𝕩
 
@@ -101,7 +101,7 @@ cdab" ┘
-

The vertical and horizontal rotations are independent, and could also be done with two s and a ˘. The multi-axis form is more convenient, and can potentially be evaluated faster that multiple separate rotations in the cases where it shows up.

+

The vertical and horizontal rotations are independent, and could also be done with two s and a ˘. The multi-axis form is more convenient, and can potentially be evaluated faster than multiple separate rotations in the cases where it shows up.

↗️
    1  2 ˘ tab
 ┌─      
 ╵"CDAB  
-- 
cgit v1.2.3