From df5ddc0ed2fe48411645228c6e2d596be239a0c6 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Mon, 4 Jul 2022 22:25:39 -0400 Subject: A few edits more --- docs/doc/fill.html | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'docs/doc/fill.html') diff --git a/docs/doc/fill.html b/docs/doc/fill.html index 3c1a0c27..dc6134b3 100644 --- a/docs/doc/fill.html +++ b/docs/doc/fill.html @@ -6,17 +6,17 @@

Fill elements

A few array operations need an array element to use when no existing element applies. BQN tries to maintain a "default" element for every array, known as a fill element, for this purpose. If it's known, the fill element is a nested array structure where each atom is either 0 or ' '. If no fill is known, a function that requests it results in an error.

-

Fills are used by Take (↑) when a value in 𝕨 is larger than the corresponding length in 𝕩, by the two Nudge functions (»«) when 𝕩 is non-empty, by Merge (>) when 𝕩 is empty, and by Reshape (β₯Š) when 𝕨 contains ↑. Except for these specific cases, the fill value an array has can't affect the program. The result of Match (≑) doesn't depend on fills, and any attempt to compute a fill can't cause side effects.

+

Fills are used by Take (↑) when a value in 𝕨 is larger than the corresponding length in 𝕩 and Reshape (β₯Š) when 𝕨 contains ↑, by the two Nudge functions (»«) when 𝕩 is non-empty, by Merge (>) and Join when 𝕩 is empty, and by Cells and Rank when the result has an empty frame. These are the only ways that an array's fill value can affect the program. The result of Match (≑) doesn't depend on fills, and any attempt to compute a fill can't cause side effects.

Using fills

-

For the examples in this section we'll use the fact that an all-number array usually has 0 as a fill while a string has ' ' (BQN maintains fills alongside array values rather than deriving them from arrays, so it's possible to construct arrays where this isn't true, but this probably wouldn't happen in ordinary code).

-

Take (↑) and Nudge (»«) in either direction use the fill for padding, to extend the array past its boundary. For example, 𝕨↑𝕩 will add elements to one side when a number in |𝕨 is larger than the corresponding length in ≒𝕩.

+

For the examples in this section we'll use the fact that an all-number array usually has 0 as a fill while a string has ' ' (it's not too rare to end up with such an array that has no fill, and possible but very unusual for an array to have a fill that conflicts with those rules).

+

Take (↑) and Nudge (»«) in either direction use the fill for padding, to extend the array past its boundary. For example, 𝕨↑𝕩 adds elements to one side if a number in |𝕨 is larger than the corresponding length in ≒𝕩.

↗️
    Β―7 ↑ 4β₯Š3     # Fill with 0
 ⟨ 0 0 0 3 3 3 3 ⟩
 
     Β―7 ↑ "qrst"  # Fill with space
 "   qrst"
 
-

Nudge Left or Right shifts the array over and places a fill in the vacated space, effectively extending it backwards by one. If 𝕩 is empty then it shouldn't give an error, but it's safer not to rely on this.

+

Nudge Left or Right shifts the array over and places a fill in the vacated space. If 𝕩 is empty then it doesn't need the fill and can't error.

↗️
    Ȭ ⟨4β₯Š3,"qrst"⟩
 ⟨ ⟨ 0 3 3 3 ⟩ " qrs" ⟩
 
@@ -26,7 +26,6 @@
     »⟨⟩   # Fill not needed
 ⟨⟩
 
-

If the argument to Merge is empty then its result will be as well, since the shape ≒𝕩 is a prefix of β‰’>𝕩. However, the remainder of the result shape is determined by the elements of 𝕩, so if there are none then Merge uses the fill element to decide what the result shape should be.

Reshape (β₯Š) uses the fill when 𝕨 contains ↑ and the product of the rest of 𝕨 doesn't evenly divide the number of elements in 𝕩.

↗️
    ↑‿8 β₯Š "completepart"
 β”Œβ”€          
@@ -38,15 +37,28 @@
 ↗️
    βŠ‘Β»1↑β₯Š"string"
 ' '
 
+

Edge cases

+

The above functions use the fill as part of their core definition. A few other functions use fills only when they encounter empty arrays. The goal of this behavior is to make programs working on empty arrays more similar to the non-empty case, so if all goes well you don't need to be thinking about these cases.

+

If the argument to Merge is empty then its result will be as well, since the shape ≒𝕩 is a prefix of β‰’>𝕩. However, the remainder of the result shape is determined by the elements of 𝕩, so if there are none then Merge uses the fill element to decide what the result shape should be. Join is similar, although it multiplies the shape of 𝕩 by the leading shape of the fill instead of concatenating them.

+↗️
    β‰’ > 2β€Ώ0β₯Š<3β€Ώ4β€Ώ1β₯Š0
+⟨ 2 0 3 4 1 ⟩
+
+    β‰’ ∾ 2β€Ώ0β₯Š<3β€Ώ4β€Ώ1β₯Š0
+⟨ 6 0 1 ⟩
+
+

Cells and Rank rely on fills in a slightly more complicated way. If one of the argument frames is empty, that means the result will be empty, but the shape of a result cell still needs to be known to determine its shape (and similarly for the fill, but that's optional). BQN implementations may try to find it by running 𝔽 using a cell of fills for the argument. As in Each (Β¨) described below, this evaluation is not allowed to produce side effects. If it doesn't work, the result cell shape is assumed to be ⟨⟩.

+↗️
    β‰’ ⌽˘ ↕0β€Ώ4β€Ώ3  # Shape is determined by fills
+⟨ 0 4 3 ⟩
+

How fills are computed

For the exact requirements placed on fill, see the specification (particularly "required functions"). This section loosely describes behavior in existing BQN implementations, and includes some parts that aren't required in the specification.

A fill element should encompass something that's necessarily true for all elements of an array. If the way an array is computed implies it's all numbers, the fill should be 0. If every element is a list of two numbers, then the fill should be ⟨0,0⟩. If every element is a list but the lengths might vary, ⟨⟩ is probably a reasonable fill element.

-

For arithmetic primitives, the fill is found by the rules of pervasion, applying the function to both argument fills. Generally this means it consists of 0, but character arithmetic also allows space fills.

+

For arithmetic primitives, the fill is found by the rules of pervasion, applying the function to both argument fills. Generally this means it consists of 0, but character arithmetic can produce space for a fill value.

↗️
    Β» "abc" + 4β€Ώ3β€Ώ2
 " ee"
 

Mapping modifiers Each and Table (¨⌜) might try to follow a similar strategy, applying 𝔽 to argument fills to obtain the result fill. The absolute rule here is that this computation can't cause side effects or an error, so for a complicated 𝔽 such as a block function this procedure is likely to be aborted to avoid disrupting the rest of the program.

-

Most other primitives fit in one of three broad categories as shown in the table below. Structural primitives, indicated by ⊒, don't change the fill of 𝕩. Combining structural primitives, indicated by ∩, only depend on the fill of all combined arraysβ€”elements of 𝕩 in the one-argument case, or 𝕨 and 𝕩 in the two-argument case. Finally, many functions such as search functions return only numbers and have a fill of 0.

+

Most other primitives fit in one of three broad categories as shown in the table below. Structural primitives, indicated by ⊒, don't change the fill of 𝕩. Combining structural primitives, indicated by ∩, only depend on the fill of all combined arraysβ€”elements of 𝕩 in the one-argument case, or 𝕨 and 𝕩 in the two-argument case. If these fills are the same value, then that's the fill; otherwise, the result has no fill. Finally, many functions such as search functions return only arrays of numbers and have a fill of 0.

-- cgit v1.2.3