diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-07-04 22:25:39 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-07-04 22:25:39 -0400 |
| commit | df5ddc0ed2fe48411645228c6e2d596be239a0c6 (patch) | |
| tree | 3a18a3674130c5aa646ac23106de3570eb03ae8d /docs | |
| parent | 81c0f0844edeb2a92f6644455c100700cab6c3c8 (diff) | |
A few edits more
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/doc/fill.html | 26 | ||||
| -rw-r--r-- | docs/doc/find.html | 8 | ||||
| -rw-r--r-- | docs/doc/fold.html | 43 |
3 files changed, 49 insertions, 28 deletions
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 @@ <div class="nav">(<a href="https://github.com/mlochbaum/BQN">github</a>) / <a href="../index.html">BQN</a> / <a href="index.html">doc</a></div> <h1 id="fill-elements"><a class="header" href="#fill-elements">Fill elements</a></h1> <p>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 <code><span class='Number'>0</span></code> or <code><span class='String'>' '</span></code>. If no fill is known, a function that requests it results in an error.</p> -<p>Fills are used by <a href="take.html">Take</a> (<code><span class='Function'>↑</span></code>) when a value in <code><span class='Value'>𝕨</span></code> is larger than the corresponding length in <code><span class='Value'>𝕩</span></code>, by the two <a href="shift.html">Nudge</a> functions (<code><span class='Function'>»«</span></code>) when <code><span class='Value'>𝕩</span></code> is non-empty, by <a href="couple.html">Merge</a> (<code><span class='Function'>></span></code>) when <code><span class='Value'>𝕩</span></code> is empty, and by <a href="reshape.html">Reshape</a> (<code><span class='Function'>⥊</span></code>) when <code><span class='Value'>𝕨</span></code> contains <code><span class='Function'>↑</span></code>. Except for these specific cases, the fill value an array has can't affect the program. The result of <a href="match.html">Match</a> (<code><span class='Function'>≡</span></code>) doesn't depend on fills, and any attempt to compute a fill can't cause side effects.</p> +<p>Fills are used by <a href="take.html">Take</a> (<code><span class='Function'>↑</span></code>) when a value in <code><span class='Value'>𝕨</span></code> is larger than the corresponding length in <code><span class='Value'>𝕩</span></code> and <a href="reshape.html">Reshape</a> (<code><span class='Function'>⥊</span></code>) when <code><span class='Value'>𝕨</span></code> contains <code><span class='Function'>↑</span></code>, by the two <a href="shift.html">Nudge</a> functions (<code><span class='Function'>»«</span></code>) when <code><span class='Value'>𝕩</span></code> is non-empty, by <a href="couple.html">Merge</a> (<code><span class='Function'>></span></code>) and <a href="join.html">Join</a> when <code><span class='Value'>𝕩</span></code> is empty, and by <a href="rank.html">Cells and Rank</a> 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 <a href="match.html">Match</a> (<code><span class='Function'>≡</span></code>) doesn't depend on fills, and any attempt to compute a fill can't cause side effects.</p> <h2 id="using-fills"><a class="header" href="#using-fills">Using fills</a></h2> -<p>For the examples in this section we'll use the fact that an all-number array usually has <code><span class='Number'>0</span></code> as a fill while a string has <code><span class='String'>' '</span></code> (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).</p> -<p><a href="take.html">Take</a> (<code><span class='Function'>↑</span></code>) and <a href="shift.html">Nudge</a> (<code><span class='Function'>»«</span></code>) in either direction use the fill for padding, to extend the array past its boundary. For example, <code><span class='Value'>𝕨</span><span class='Function'>↑</span><span class='Value'>𝕩</span></code> will add elements to one side when a number in <code><span class='Function'>|</span><span class='Value'>𝕨</span></code> is larger than the corresponding length in <code><span class='Function'>≢</span><span class='Value'>𝕩</span></code>.</p> +<p>For the examples in this section we'll use the fact that an all-number array usually has <code><span class='Number'>0</span></code> as a fill while a string has <code><span class='String'>' '</span></code> (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).</p> +<p><a href="take.html">Take</a> (<code><span class='Function'>↑</span></code>) and <a href="shift.html">Nudge</a> (<code><span class='Function'>»«</span></code>) in either direction use the fill for padding, to extend the array past its boundary. For example, <code><span class='Value'>𝕨</span><span class='Function'>↑</span><span class='Value'>𝕩</span></code> adds elements to one side if a number in <code><span class='Function'>|</span><span class='Value'>𝕨</span></code> is larger than the corresponding length in <code><span class='Function'>≢</span><span class='Value'>𝕩</span></code>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=wq83IOKGkSA04qWKMyAgICAgIyBGaWxsIHdpdGggMAoKwq83IOKGkSAicXJzdCIgICMgRmlsbCB3aXRoIHNwYWNl">↗️</a><pre> <span class='Number'>¯7</span> <span class='Function'>↑</span> <span class='Number'>4</span><span class='Function'>⥊</span><span class='Number'>3</span> <span class='Comment'># Fill with 0 </span>⟨ 0 0 0 3 3 3 3 ⟩ <span class='Number'>¯7</span> <span class='Function'>↑</span> <span class='String'>"qrst"</span> <span class='Comment'># Fill with space </span>" qrst" </pre> -<p>Nudge Left or Right shifts the array over and places a fill in the vacated space, effectively extending it backwards by one. If <code><span class='Value'>𝕩</span></code> is empty then it shouldn't give an error, but it's safer not to rely on this.</p> +<p>Nudge Left or Right shifts the array over and places a fill in the vacated space. If <code><span class='Value'>𝕩</span></code> is empty then it doesn't need the fill and can't error.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=wrvCqCDin6g04qWKMywicXJzdCLin6kKCjPihpHin6jin6kgICMgRmlsbCB1bmtub3duCgrCu+KfqOKfqSAgICMgRmlsbCBub3QgbmVlZGVk">↗️</a><pre> <span class='Function'>»</span><span class='Modifier'>¨</span> <span class='Bracket'>⟨</span><span class='Number'>4</span><span class='Function'>⥊</span><span class='Number'>3</span><span class='Separator'>,</span><span class='String'>"qrst"</span><span class='Bracket'>⟩</span> ⟨ ⟨ 0 3 3 3 ⟩ " qrs" ⟩ @@ -26,7 +26,6 @@ <span class='Function'>»</span><span class='Bracket'>⟨⟩</span> <span class='Comment'># Fill not needed </span>⟨⟩ </pre> -<p>If the argument to <a href="couple.html">Merge</a> is empty then its result will be as well, since the shape <code><span class='Function'>≢</span><span class='Value'>𝕩</span></code> is a prefix of <code><span class='Function'>≢></span><span class='Value'>𝕩</span></code>. However, the remainder of the result shape is determined by the elements of <code><span class='Value'>𝕩</span></code>, so if there are none then Merge uses the fill element to decide what the result shape should be.</p> <p><a href="reshape.html#computed-lengths">Reshape</a> (<code><span class='Function'>⥊</span></code>) uses the fill when <code><span class='Value'>𝕨</span></code> contains <code><span class='Function'>↑</span></code> and the product of the rest of <code><span class='Value'>𝕨</span></code> doesn't evenly divide the number of elements in <code><span class='Value'>𝕩</span></code>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oaR4oC/OCDipYogImNvbXBsZXRlcGFydCI=">↗️</a><pre> <span class='Function'>↑</span><span class='Ligature'>‿</span><span class='Number'>8</span> <span class='Function'>⥊</span> <span class='String'>"completepart"</span> ┌─ @@ -38,15 +37,28 @@ <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqRwrsx4oaR4qWKInN0cmluZyI=">↗️</a><pre> <span class='Function'>⊑»</span><span class='Number'>1</span><span class='Function'>↑⥊</span><span class='String'>"string"</span> ' ' </pre> +<h2 id="edge-cases"><a class="header" href="#edge-cases">Edge cases</a></h2> +<p>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.</p> +<p>If the argument to <a href="couple.html">Merge</a> is empty then its result will be as well, since the shape <code><span class='Function'>≢</span><span class='Value'>𝕩</span></code> is a prefix of <code><span class='Function'>≢></span><span class='Value'>𝕩</span></code>. However, the remainder of the result shape is determined by the elements of <code><span class='Value'>𝕩</span></code>, so if there are none then Merge uses the fill element to decide what the result shape should be. <a href="join.html">Join</a> is similar, although it multiplies the shape of <code><span class='Value'>𝕩</span></code> by the leading shape of the fill instead of concatenating them.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omiID4gMuKAvzDipYo8M+KAvzTigL8x4qWKMAoK4omiIOKIviAy4oC/MOKlijwz4oC/NOKAvzHipYow">↗️</a><pre> <span class='Function'>≢</span> <span class='Function'>></span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Function'>⥊<</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Function'>⥊</span><span class='Number'>0</span> +⟨ 2 0 3 4 1 ⟩ + + <span class='Function'>≢</span> <span class='Function'>∾</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Function'>⥊<</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Function'>⥊</span><span class='Number'>0</span> +⟨ 6 0 1 ⟩ +</pre> +<p><a href="rank.html">Cells and Rank</a> 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 <code><span class='Function'>𝔽</span></code> using a cell of fills for the argument. As in Each (<code><span class='Modifier'>¨</span></code>) described below, this evaluation is not allowed to produce side effects. If it doesn't work, the result cell shape is assumed to be <code><span class='Bracket'>⟨⟩</span></code>.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omiIOKMvcuYIOKGlTDigL804oC/MyAgIyBTaGFwZSBpcyBkZXRlcm1pbmVkIGJ5IGZpbGxz">↗️</a><pre> <span class='Function'>≢</span> <span class='Function'>⌽</span><span class='Modifier'>˘</span> <span class='Function'>↕</span><span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>3</span> <span class='Comment'># Shape is determined by fills +</span>⟨ 0 4 3 ⟩ +</pre> <h2 id="how-fills-are-computed"><a class="header" href="#how-fills-are-computed">How fills are computed</a></h2> <p>For the exact requirements placed on fill, see <a href="../spec/inferred.html#fill-elements">the specification</a> (particularly "required functions"). This section loosely describes behavior in existing BQN implementations, and includes some parts that aren't required in the specification.</p> <p>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 <code><span class='Number'>0</span></code>. If every element is a list of two numbers, then the fill should be <code><span class='Bracket'>⟨</span><span class='Number'>0</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Bracket'>⟩</span></code>. If every element is a list but the lengths might vary, <code><span class='Bracket'>⟨⟩</span></code> is probably a reasonable fill element.</p> -<p>For <a href="arithmetic.html">arithmetic</a> primitives, the fill is found by the rules of pervasion, applying the function to both argument fills. Generally this means it consists of <code><span class='Number'>0</span></code>, but character arithmetic also allows space fills.</p> +<p>For <a href="arithmetic.html">arithmetic</a> primitives, the fill is found by the rules of pervasion, applying the function to both argument fills. Generally this means it consists of <code><span class='Number'>0</span></code>, but <a href="arithmetic.html#character-arithmetic">character arithmetic</a> can produce space for a fill value.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=wrsgImFiYyIgKyA04oC/M+KAvzI=">↗️</a><pre> <span class='Function'>»</span> <span class='String'>"abc"</span> <span class='Function'>+</span> <span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>2</span> " ee" </pre> <p><a href="map.html">Mapping</a> modifiers Each and Table (<code><span class='Modifier'>¨⌜</span></code>) might try to follow a similar strategy, applying <code><span class='Function'>𝔽</span></code> 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 <code><span class='Function'>𝔽</span></code> such as a block function this procedure is likely to be aborted to avoid disrupting the rest of the program.</p> -<p>Most other primitives fit in one of three broad categories as shown in the table below. Structural primitives, indicated by <code><span class='Function'>⊢</span></code>, don't change the fill of <code><span class='Value'>𝕩</span></code>. Combining structural primitives, indicated by <code><span class='Value'>∩</span></code>, only depend on the fill of all combined arrays—elements of <code><span class='Value'>𝕩</span></code> in the one-argument case, or <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> in the two-argument case. Finally, many functions such as <a href="search.html">search functions</a> return only numbers and have a fill of <code><span class='Number'>0</span></code>.</p> +<p>Most other primitives fit in one of three broad categories as shown in the table below. Structural primitives, indicated by <code><span class='Function'>⊢</span></code>, don't change the fill of <code><span class='Value'>𝕩</span></code>. Combining structural primitives, indicated by <code><span class='Value'>∩</span></code>, only depend on the fill of all combined arrays—elements of <code><span class='Value'>𝕩</span></code> in the one-argument case, or <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> 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 <a href="search.html">search functions</a> return only arrays of numbers and have a fill of <code><span class='Number'>0</span></code>.</p> <table> <thead> <tr> diff --git a/docs/doc/find.html b/docs/doc/find.html index 09632469..01efff6d 100644 --- a/docs/doc/find.html +++ b/docs/doc/find.html @@ -9,7 +9,7 @@ <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Inh4IiDijbcgInh4YmR4eHhjeCI=">↗️</a><pre> <span class='String'>"xx"</span> <span class='Function'>⍷</span> <span class='String'>"xxbdxxxcx"</span> ⟨ 1 0 0 0 1 1 0 0 ⟩ </pre> -<p>More precisely <code><span class='Value'>𝕨</span></code> needs to <a href="match.html">match</a> a contiguous selection from <code><span class='Value'>𝕩</span></code>, which for strings means a substring. These subarrays of <code><span class='Value'>𝕩</span></code> are also exactly the cells in the result of <a href="windows.html">Windows</a>. In fact we can use Windows to see all the arrays <code><span class='Value'>𝕨</span></code> will be compared against.</p> +<p>More precisely, <code><span class='Value'>𝕨</span></code> needs to <a href="match.html">match</a> a contiguous selection from <code><span class='Value'>𝕩</span></code>, which for strings means a substring. These subarrays of <code><span class='Value'>𝕩</span></code> are also exactly the cells in the result of <a href="windows.html">Windows</a>. So we can use Windows to see all the arrays <code><span class='Value'>𝕨</span></code> will be compared against.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MiDihpUgInh4YmR4eHhjeCIKCiJ4eCLiirjiiaHLmCAyIOKGlSAieHhiZHh4eGN4Ig==">↗️</a><pre> <span class='Number'>2</span> <span class='Function'>↕</span> <span class='String'>"xxbdxxxcx"</span> ┌─ ╵"xx @@ -32,7 +32,7 @@ <span class='String'>"string"</span> <span class='Paren'>(</span><span class='Function'>≢</span><span class='Modifier2'>∘</span><span class='Function'>⊢↑⍷</span><span class='Paren'>)</span> <span class='String'>"substring"</span> <span class='Comment'># APL style </span>⟨ 0 0 0 1 0 0 0 0 0 ⟩ </pre> -<p>If <code><span class='Value'>𝕨</span></code> is larger than <code><span class='Value'>𝕩</span></code>, the result is empty, and there's no error even in cases where Windows would fail. One place this tends to come up is when applying <a href="pick.html#first">First</a> (<code><span class='Function'>⊑</span></code>) the result: <code><span class='Function'>⊑⍷</span></code> tests whether <code><span class='Value'>𝕨</span></code> appears in <code><span class='Value'>𝕩</span></code> at the first position, that is, whether it's a prefix of <code><span class='Value'>𝕩</span></code>. If <code><span class='Value'>𝕨</span></code> is longer than <code><span class='Value'>𝕩</span></code> it shouldn't be a prefix. First will fail but using a <a href="fold.html">fold</a> <code><span class='Number'>0</span><span class='Function'>⊣</span><span class='Modifier'>´</span><span class='Function'>⥊</span><span class='Modifier2'>∘</span><span class='Function'>⍷</span></code> instead gives a 0 in this case.</p> +<p>If <code><span class='Value'>𝕨</span></code> is larger than <code><span class='Value'>𝕩</span></code>, the result is empty, and there's no error even in cases where Windows would fail. One place this tends to come up is when applying <a href="pick.html#first">First</a> (<code><span class='Function'>⊑</span></code>) to the result: <code><span class='Function'>⊑⍷</span></code> tests whether <code><span class='Value'>𝕨</span></code> appears in <code><span class='Value'>𝕩</span></code> at the first position, that is, whether it's a prefix of <code><span class='Value'>𝕩</span></code>. If <code><span class='Value'>𝕨</span></code> is longer than <code><span class='Value'>𝕩</span></code> it shouldn't be a prefix. First will fail but using a <a href="fold.html">fold</a> <code><span class='Number'>0</span><span class='Function'>⊣</span><span class='Modifier'>´</span><span class='Function'>⍷</span></code> instead gives a 0 in this case.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Imxvb29vb29uZyIg4o23ICJzaG9ydCIKCjkg4oaVICJzaG9ydCIKCjAg4oqjwrQgImxvb29vb29uZyIg4o23ICJzaG9ydCI=">↗️</a><pre> <span class='String'>"loooooong"</span> <span class='Function'>⍷</span> <span class='String'>"short"</span> ⟨⟩ @@ -42,7 +42,7 @@ <span class='Number'>0</span> <span class='Function'>⊣</span><span class='Modifier'>´</span> <span class='String'>"loooooong"</span> <span class='Function'>⍷</span> <span class='String'>"short"</span> 0 </pre> -<p>This pattern also works in the high-rank case discussed below, testing whether <code><span class='Value'>𝕨</span></code> is a multi-dimensional prefix starting at the lowest-index corner of <code><span class='Value'>𝕩</span></code>.</p> +<p>Adding a <a href="reshape.html#deshape">Deshape</a> gives <code><span class='Number'>0</span><span class='Function'>⊣</span><span class='Modifier'>´</span><span class='Function'>⥊</span><span class='Modifier2'>∘</span><span class='Function'>⍷</span></code>, which works with the high-rank case discussed below. It tests whether <code><span class='Value'>𝕨</span></code> is a multi-dimensional prefix starting at the lowest-index corner of <code><span class='Value'>𝕩</span></code>.</p> <h3 id="higher-ranks"><a class="header" href="#higher-ranks">Higher ranks</a></h3> <p>If <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> are two-dimensional then Find does a two-dimensional search. The cells used are also found in <code><span class='Value'>𝕨</span><span class='Function'>≢</span><span class='Modifier2'>⊸</span><span class='Function'>↕</span><span class='Value'>𝕩</span></code>. For example, the bottom-right corner of <code><span class='Value'>𝕩</span></code> below matches <code><span class='Value'>𝕨</span></code>, so there's a 1 in the bottom-right corner of the result.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIGEg4oaQIDcgKDR84ouGy5wp4oyc4peL4oaVIDkgICAjIEFycmF5IHdpdGggcGF0dGVybnMKCigw4oC/M+KAvzDiiY0w4oC/MeKAvzApIOKNtyBh">↗️</a><pre> <span class='Function'>⊢</span> <span class='Value'>a</span> <span class='Gets'>←</span> <span class='Number'>7</span> <span class='Paren'>(</span><span class='Number'>4</span><span class='Function'>|⋆</span><span class='Modifier'>˜</span><span class='Paren'>)</span><span class='Modifier'>⌜</span><span class='Modifier2'>○</span><span class='Function'>↕</span> <span class='Number'>9</span> <span class='Comment'># Array with patterns @@ -66,7 +66,7 @@ 0 0 1 0 0 0 1 ┘ </pre> -<p>It's also allowed for <code><span class='Value'>𝕨</span></code> to have a smaller rank than <code><span class='Value'>𝕩</span></code>; in this case leading axes of <code><span class='Value'>𝕩</span></code> are mapped over so that axes of <code><span class='Value'>𝕨</span></code> correspond to trailing axes of <code><span class='Value'>𝕩</span></code>. This is a minor violation of the <a href="leading.html">leading axis</a> principle, which would match axes of <code><span class='Value'>𝕨</span></code> to leading axes of <code><span class='Value'>𝕩</span></code> in order to make a function that's useful with the Rank operator, but such a function would be quite strange and hardly ever useful.</p> +<p>It's also allowed for <code><span class='Value'>𝕨</span></code> to have a smaller rank than <code><span class='Value'>𝕩</span></code>; the axes of <code><span class='Value'>𝕨</span></code> then correspond to trailing axes of <code><span class='Value'>𝕩</span></code>, so that leading axes of <code><span class='Value'>𝕩</span></code> are mapped over. This is a minor violation of the <a href="leading.html">leading axis</a> principle, which would match axes of <code><span class='Value'>𝕨</span></code> to leading axes of <code><span class='Value'>𝕩</span></code> in order to make a function that's useful with the Rank operator, but such a function would be quite strange and hardly ever useful.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=MOKAvzHigL8w4oC/MSDijbcgYQ==">↗️</a><pre> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>1</span> <span class='Function'>⍷</span> <span class='Value'>a</span> ┌─ ╵ 0 0 0 0 0 0 diff --git a/docs/doc/fold.html b/docs/doc/fold.html index f1dc9a59..5b024ff4 100644 --- a/docs/doc/fold.html +++ b/docs/doc/fold.html @@ -42,7 +42,7 @@ </svg> <p>The closely related 1-modifiers Fold (<code><span class='Modifier'>´</span></code>) and Insert (<code><span class='Modifier'>˝</span></code>) apply a dyadic operand function <code><span class='Function'>𝔽</span></code> repeatedly between elements or major cells of <code><span class='Value'>𝕩</span></code>. Neither is quite like the APL2-style Reduce operator (<code><span class='Function'>/</span></code> or <code><span class='Value'>⌿</span></code> in APL), although I sometimes use the term "reduction" to mean either Fold or Insert. There are a bunch of other names like "accumulate" and "aggregate" for this class of calculations—I don't know which is best but I know "catamorphism" is worst.</p> -<p>A distinguishing feature of APL-family reductions is that they don't use an initial value, and try to derive an "identity element" from the operand if the argument array is empty. BQN retains this capability but also allows the programmer to supply an initial value as <code><span class='Value'>𝕨</span></code>.</p> +<p>A distinguishing feature of APL-family reductions is that they don't use an initial value, and try to derive an "identity element" for <code><span class='Function'>𝔽</span></code> if the argument array is empty. BQN retains this capability but also allows the programmer to supply an initial value as <code><span class='Value'>𝕨</span></code>.</p> <h2 id="fold"><a class="header" href="#fold">Fold</a></h2> <p>As its glyph suggests, Fold is slightly simpler than Insert. The argument <code><span class='Value'>𝕩</span></code> must always be a list, and Fold applies <code><span class='Function'>𝔽</span></code> between elements—always two at a time—of the list to yield a single result value. In this sense, <code><span class='Function'>𝔽</span><span class='Modifier'>´</span></code> removes a layer of <a href="depth.html">depth</a> from <code><span class='Value'>𝕩</span></code>, although it's not necessarily true that the depth of <code><span class='Function'>𝔽</span><span class='Modifier'>´</span><span class='Value'>𝕩</span></code> is less than that of <code><span class='Value'>𝕩</span></code> because the function <code><span class='Function'>𝔽</span></code> might increase depth.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=K8K0IDLigL804oC/M+KAvzEKK8K0IOKfqDLigL80LCAz4oC/MeKfqQ==">↗️</a><pre> <span class='Function'>+</span><span class='Modifier'>´</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>1</span> @@ -50,7 +50,7 @@ <span class='Function'>+</span><span class='Modifier'>´</span> <span class='Bracket'>⟨</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Separator'>,</span> <span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Bracket'>⟩</span> ⟨ 5 5 ⟩ </pre> -<p>Any function can be used as an operand. With Maximum (<code><span class='Function'>⌈</span></code>) you can find the largest number out of an entire list, and likewise for Minimum (<code><span class='Function'>⌊</span></code>).</p> +<p>Any function can be used as an operand. You can find the largest number out of an entire list with Maximum (<code><span class='Function'>⌈</span></code>), or the smallest with Minimum (<code><span class='Function'>⌊</span></code>).</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oyIwrQgMuKAvzTigL8z4oC/MQrijIrCtCAy4oC/NOKAvzPigL8xCsOXwrQgMuKAvzTigL8z4oC/MSAgIyBQcm9kdWN0IGFzIHdlbGw=">↗️</a><pre> <span class='Function'>⌈</span><span class='Modifier'>´</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>1</span> 4 <span class='Function'>⌊</span><span class='Modifier'>´</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>3</span><span class='Ligature'>‿</span><span class='Number'>1</span> @@ -77,7 +77,7 @@ <span class='Function'>∧</span><span class='Modifier'>´</span> <span class='Bracket'>⟨⟩</span> <span class='Comment'># All the elements in the list are true… </span>1 </pre> -<p>The full list of identity values Fold has to use is shown below.</p> +<p>Here's the full list of identity values Fold has to support.</p> <table> <thead> <tr> @@ -140,7 +140,7 @@ <span class='String'>'a'</span> <span class='Function'>⋈</span> <span class='String'>'b'</span> <span class='Function'>⋈</span> <span class='String'>'c'</span> <span class='Function'>⋈</span> <span class='String'>'d'</span> <span class='Comment'># Expanded form </span>⟨ 'a' ⟨ 'b' "cd" ⟩ ⟩ </pre> -<p>Using <a href="pair.html">Pair</a> (<code><span class='Function'>⋈</span></code>) as an operand shows the structure nicely. This fold first pairs the final two characters <code><span class='String'>'c'</span></code> and <code><span class='String'>'d'</span></code>, then pairs <code><span class='String'>'b'</span></code> with that and so on. This matches BQN's right-to-left order of evaluation. More declaratively we might say that each character is paired with the result of folding over everything to its right.</p> +<p><a href="pair.html">Pair</a> (<code><span class='Function'>⋈</span></code>) as an operand shows the structure nicely. This fold first pairs the final two characters <code><span class='String'>'c'</span></code> and <code><span class='String'>'d'</span></code>, then pairs <code><span class='String'>'b'</span></code> with that and so on. This matches BQN's right-to-left order of evaluation. More declaratively we might say that each character is paired with the result of folding over everything to its right.</p> <p>BQN doesn't provide a left Fold (<code><span class='Modifier'>`</span></code> is <a href="scan.html">Scan</a>). However, you can fold from the left by <a href="reverse.html#reverse">reversing</a> (<code><span class='Function'>⌽</span></code>) the argument list and also reversing (<code><span class='Modifier'>˜</span></code>) the operand function's argument order.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4ouIy5zCtCDijL0gImFiY2Qi">↗️</a><pre> <span class='Function'>⋈</span><span class='Modifier'>˜´</span> <span class='Function'>⌽</span> <span class='String'>"abcd"</span> ⟨ ⟨ "ab" 'c' ⟩ 'd' ⟩ @@ -149,12 +149,12 @@ <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=LcK0IDMw4oC/MeKAvzIw4oC/MuKAvzEw">↗️</a><pre> <span class='Function'>-</span><span class='Modifier'>´</span> <span class='Number'>30</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>20</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>10</span> 57 </pre> -<p>The operand <code><span class='Function'>+</span><span class='Modifier2'>⟜</span><span class='Function'>÷</span></code> is a quick way to compute a <a href="https://en.wikipedia.org/wiki/Continued_fraction">continued fraction</a>'s value from a list of numbers. Here are a few terms from the continued fraction for <em>e</em>.</p> +<p>And the operand <code><span class='Function'>+</span><span class='Modifier2'>⟜</span><span class='Function'>÷</span></code> is a quick way to compute a <a href="https://en.wikipedia.org/wiki/Continued_fraction">continued fraction</a>'s value from a list of numbers. Here are a few terms from the continued fraction for <em>e</em>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=K+KfnMO3wrQgMuKAvzHigL8y4oC/MeKAvzHigL804oC/MeKAvzE=">↗️</a><pre> <span class='Function'>+</span><span class='Modifier2'>⟜</span><span class='Function'>÷</span><span class='Modifier'>´</span> <span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>1</span><span class='Ligature'>‿</span><span class='Number'>1</span> 2.71830985915493 </pre> <h3 id="initial-element"><a class="header" href="#initial-element">Initial element</a></h3> -<p>When the operand isn't just an arithmetic primitive, folding with no initial element can be dangerous. Even if you know <code><span class='Value'>𝕩</span></code> isn't empty, saving you from an "Identity not found" error, the case with only one element can easily violate expectations. Here's a somewhat silly example of a function meant to merge elements of the argument into a single list (<code><span class='Function'>∾⥊</span><span class='Modifier'>¨</span></code> is a much better way to do this):</p> +<p>When <code><span class='Function'>𝔽</span></code> isn't just an arithmetic primitive, folding with no initial element can be dangerous. Even if you know <code><span class='Value'>𝕩</span></code> isn't empty, saving you from an "Identity not found" error, the case with only one element can easily violate expectations. Here's a somewhat silly example of a function meant to merge elements of the argument into a single list (<code><span class='Function'>∾⥊</span><span class='Modifier'>¨</span></code> is a much better way to do this):</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oi+4peL4qWKwrQg4p+oMuKAvzTiiY024oC/OCwiYWJjZCIsMOKfqQoK4oi+4peL4qWKwrQg4p+oMuKAvzTiiY024oC/OCwiYWJjZCLin6kKCuKIvuKXi+KlisK0IOKfqDLigL804omNNuKAvzjin6k=">↗️</a><pre> <span class='Function'>∾</span><span class='Modifier2'>○</span><span class='Function'>⥊</span><span class='Modifier'>´</span> <span class='Bracket'>⟨</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Function'>≍</span><span class='Number'>6</span><span class='Ligature'>‿</span><span class='Number'>8</span><span class='Separator'>,</span><span class='String'>"abcd"</span><span class='Separator'>,</span><span class='Number'>0</span><span class='Bracket'>⟩</span> ⟨ 2 4 6 8 'a' 'b' 'c' 'd' 0 ⟩ @@ -168,11 +168,11 @@ ┘ </pre> <p>The result always has rank 1, until the one-element case, when <code><span class='Function'>∾</span><span class='Modifier2'>○</span><span class='Function'>⥊</span></code> is never applied and can't deshape anything. Using Fold with lots of complex operands and no initial element can make a program fragile.</p> -<p>However, it's easy to specify an initial element for Fold: simply pass it as <code><span class='Value'>𝕨</span></code>. Because <code><span class='Value'>𝕨</span></code> behaves like an element of <code><span class='Value'>𝕩</span></code>, it doesn't need to be enclosed and will usually have one smaller depth. For <code><span class='Function'>∾</span><span class='Modifier2'>○</span><span class='Function'>⥊</span></code> the natural starting element for a fold that returns a list is the empty list.</p> +<p>The left argument, if given, is the initial right argument to <code><span class='Function'>𝔽</span></code>. This puts <code><span class='Value'>𝕨</span></code> on the same level as an element of <code><span class='Value'>𝕩</span></code>, so it doesn't need to be enclosed and will usually have one smaller depth. For <code><span class='Function'>∾</span><span class='Modifier2'>○</span><span class='Function'>⥊</span><span class='Modifier'>´</span></code> the natural starting element is the empty list.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4p+o4p+pIOKIvuKXi+KlisK0IOKfqDLigL804omNNuKAvzjin6k=">↗️</a><pre> <span class='Bracket'>⟨⟩</span> <span class='Function'>∾</span><span class='Modifier2'>○</span><span class='Function'>⥊</span><span class='Modifier'>´</span> <span class='Bracket'>⟨</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Function'>≍</span><span class='Number'>6</span><span class='Ligature'>‿</span><span class='Number'>8</span><span class='Bracket'>⟩</span> ⟨ 2 4 6 8 ⟩ </pre> -<p>The initial element is used in the first function application, so it behaves as though it's added to the end of the list (<code><span class='Function'>∾</span><span class='Modifier2'>⟜</span><span class='Function'><</span><span class='Modifier'>˜</span></code> would accomplish this as well).</p> +<p>With a non-empty <code><span class='Value'>𝕨</span></code> we can see it's placed at the end of the result list, because it's passed to <code><span class='Function'>𝔽</span></code> before any elements of <code><span class='Value'>𝕩</span></code>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImVuZCIg4oi+4peL4qWKwrQg4p+oInN0YXJ0IiwibWlkZGxlIuKfqQ==">↗️</a><pre> <span class='String'>"end"</span> <span class='Function'>∾</span><span class='Modifier2'>○</span><span class='Function'>⥊</span><span class='Modifier'>´</span> <span class='Bracket'>⟨</span><span class='String'>"start"</span><span class='Separator'>,</span><span class='String'>"middle"</span><span class='Bracket'>⟩</span> "startmiddleend" </pre> @@ -194,24 +194,24 @@ <span class='Function'>+</span><span class='Modifier'>˝</span> <span class='Value'>tab</span> ⟨ 9 7 12 ⟩ </pre> -<p>The Insert (<code><span class='Modifier'>˝</span></code>) modifier will do this for you. Because it works on the <a href="leading.html">leading axis</a> of the argument, Insert can be applied to axes other than the first with Rank. Sum each row (second axis) with <code><span class='Modifier'>˘</span></code>, for example.</p> +<p>The Insert (<code><span class='Modifier'>˝</span></code>) modifier will do this for you. And because it works on the <a href="leading.html">leading axis</a> of the argument, Insert can be applied to axes other than the first with Rank. Sum each row (second axis) with <a href="rank.html#cells">Cells</a> (<code><span class='Modifier'>˘</span></code>), for example.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=K8udy5ggdGFi">↗️</a><pre> <span class='Function'>+</span><span class='Modifier'>˝˘</span> <span class='Value'>tab</span> ⟨ 2 3 6 5 12 ⟩ </pre> -<p>This case is tricky, because <code><span class='Function'>+</span><span class='Modifier'>´˘</span> <span class='Value'>tab</span></code> yields the same result but is actually unsound—if <code><span class='Value'>tab</span></code> contains arrays then they will be merged together at the end. Remember that if you want to reduce along one axis of an array but get an array of results out, you should use Insert (possibly adding Each to work on elements instead of cells; see <a href="#apl2-reduction">APL2 reduction</a> below).</p> +<p>This case is tricky, because <code><span class='Function'>+</span><span class='Modifier'>´˘</span> <span class='Value'>tab</span></code> yields the same result but is actually unsound—if <code><span class='Value'>tab</span></code> contains arrays then they will be merged together at the end. Remember: if you want to reduce along one axis of an array and get an array of results out, you should use Insert (possibly adding Each to work on elements instead of cells; see <a href="#apl2-reduction">APL2 reduction</a> below).</p> <p>A function with Insert <code><span class='Function'>𝔽</span><span class='Modifier'>˝</span></code> is nearly equivalent to <code><span class='Function'>𝔽</span><span class='Modifier'>´</span><span class='Function'><</span><span class='Modifier'>˘</span></code> (and both fail on unit arguments, because there's no axis to apply along). Besides being more convenient, <code><span class='Function'>𝔽</span><span class='Modifier'>˝</span></code> is a little safer because it takes the argument shape into account when returning an identity value:</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=K8K0PMuYIDDigL804qWKMAory50gICAw4oC/NOKlijA=">↗️</a><pre> <span class='Function'>+</span><span class='Modifier'>´</span><span class='Function'><</span><span class='Modifier'>˘</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Function'>⥊</span><span class='Number'>0</span> 0 <span class='Function'>+</span><span class='Modifier'>˝</span> <span class='Number'>0</span><span class='Ligature'>‿</span><span class='Number'>4</span><span class='Function'>⥊</span><span class='Number'>0</span> ⟨ 0 0 0 0 ⟩ </pre> -<p>Just like Fold, Insert allows an initial element for the left argument, so that you don't need to rely on the interpreter knowing the identity. A more complete translation into Fold is therefore <code><span class='Brace'>{</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier'>´</span><span class='Function'><</span><span class='Modifier'>˘</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>. The expression below shows that the operand function is called on the last major cell when the identity, then the next-to-last major cell and so on. In total there are <code><span class='Function'>≠</span><span class='Value'>𝕩</span></code> calls, while there would be <code><span class='Number'>1</span><span class='Function'>-</span><span class='Modifier'>˜</span><span class='Function'>≠</span><span class='Value'>𝕩</span></code> without the left argument.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImlkIiDii4jLnSAicm93MCAi4oi+InJvdzEgIuKJjSJyb3cyICI=">↗️</a><pre> <span class='String'>"id"</span> <span class='Function'>⋈</span><span class='Modifier'>˝</span> <span class='String'>"row0 "</span><span class='Function'>∾</span><span class='String'>"row1 "</span><span class='Function'>≍</span><span class='String'>"row2 "</span> +<p>Just like Fold, Insert allows an initial element for the left argument, so that you don't need to rely on the interpreter knowing the identity (in Fold terms it's <code><span class='Brace'>{</span><span class='Value'>𝕨</span><span class='Function'>𝔽</span><span class='Modifier'>´</span><span class='Function'><</span><span class='Modifier'>˘</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>). Below, we see that <code><span class='Function'>𝔽</span></code> is called on the last major cell and <code><span class='Value'>𝕨</span></code>, then the next-to-last major cell and so on. This makes <code><span class='Function'>≠</span><span class='Value'>𝕩</span></code> calls, while there would be <code><span class='Number'>1</span><span class='Function'>-</span><span class='Modifier'>˜</span><span class='Function'>≠</span><span class='Value'>𝕩</span></code> without the initial value.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImlkIiDii4jLnSBbInJvdzAgIiwicm93MSAiLCJyb3cyICJd">↗️</a><pre> <span class='String'>"id"</span> <span class='Function'>⋈</span><span class='Modifier'>˝</span> <span class='Bracket'>[</span><span class='String'>"row0 "</span><span class='Separator'>,</span><span class='String'>"row1 "</span><span class='Separator'>,</span><span class='String'>"row2 "</span><span class='Bracket'>]</span> ┌─ · "row0 " ⟨ "row1 " ⟨ "row2 " "id" ⟩ ⟩ ┘ </pre> -<p>One trick involving Insert is <code><span class='Function'>∾</span><span class='Modifier'>˝</span></code>, which merges the first two axes of <code><span class='Value'>𝕩</span></code> into one long axis. It even works on empty arrays, because BQN knows that there's only one result shape that makes sense (in contrast to <code><span class='Function'>∾</span><span class='Modifier'>´</span><span class='Bracket'>⟨⟩</span></code>, where many results sometimes work but none of them always work).</p> +<p>One trick involving Insert is <code><span class='Function'>∾</span><span class='Modifier'>˝</span></code>, which uses <a href="join.html#join-to">Join to</a> to merge the first two axes of <code><span class='Value'>𝕩</span></code> into one long axis. It even works on empty arrays, because BQN knows that there's only one result shape that makes sense (unlike <code><span class='Function'>∾</span><span class='Modifier'>´</span><span class='Bracket'>⟨⟩</span></code>, where many results sometimes fit but none of them always fit).</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIGxldCDihpAgKCJBSFciLSdBJykgK+KMnCAiYUEiICvijJwg4oaVNAoK4oi+y50gbGV0CgriiaIg4oi+y50g4oaVM+KAvzLigL80CgriiaIg4oi+y50g4oaVMOKAvzLigL80ICAjIFRoZSBpZGVudGl0eSBpcyBhbiBlbXB0eSBjZWxs">↗️</a><pre> <span class='Function'>⊢</span> <span class='Value'>let</span> <span class='Gets'>←</span> <span class='Paren'>(</span><span class='String'>"AHW"</span><span class='Function'>-</span><span class='String'>'A'</span><span class='Paren'>)</span> <span class='Function'>+</span><span class='Modifier'>⌜</span> <span class='String'>"aA"</span> <span class='Function'>+</span><span class='Modifier'>⌜</span> <span class='Function'>↕</span><span class='Number'>4</span> ┌─ ╎"abcd @@ -242,12 +242,21 @@ </pre> <p>As a historical note, Insert is named after J's adverb <code><span class='Function'>/</span></code>, which comes from SHARP APL's <code><span class='Value'>⌿</span></code>, reduce-down. In the original APL, only arithmetic reductions were defined, and nested arrays didn't exist—arrays were either all characters or all numbers. SHARP extended them by splitting the array into cells as we've shown. However, there's another interpretation, which is what you'll find in mainstream APLs today…</p> <h2 id="apl2-reduction"><a class="header" href="#apl2-reduction">APL2 reduction?</a></h2> -<p>If you try an expression like <code><span class='Value'>⍪⌿</span></code> in Dyalog APL, you'll get results very different from BQN's <code><span class='Function'>∾</span><span class='Modifier'>˝</span></code>. Instead of combining the cells like we see above, APL applies the function on pairs of <em>elements</em> much like Fold. The difference is that, because reduction happens only along one axis but an array might have other axes, there can be multiple values in the result, so that it will always be an array like the argument. BQN can perform this operation as well: <code><span class='Value'>⍪⌿</span></code> is written <code><span class='Function'>∾</span><span class='Modifier'>¨˝</span></code> in BQN.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oi+wqjLnSB0YWI=">↗️</a><pre> <span class='Function'>∾</span><span class='Modifier'>¨˝</span> <span class='Value'>tab</span> +<p>The function <code><span class='Value'>⍪⌿</span></code> in Dyalog APL gives very different results from BQN's <code><span class='Function'>∾</span><span class='Modifier'>˝</span></code>. Instead of combining the cells like we see above, APL applies the function on pairs of <em>elements</em> much like Fold. The difference is that, because reduction happens only along one axis but an array might have other axes, there can be multiple values in the result, so that it will always be an array like the argument. BQN can perform this operation as well: <code><span class='Value'>⍪⌿</span></code> is written <code><span class='Function'>∾</span><span class='Modifier'>¨˝</span></code> in BQN (but please use <code><span class='Function'><</span><span class='Modifier'>˘</span><span class='Function'>⍉</span></code> instead).</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=dGFiCgriiL7CqMudIHRhYg==">↗️</a><pre> <span class='Value'>tab</span> +┌─ +╵ 1 0 1 + 0 1 2 + 1 2 3 + 4 0 1 + 3 4 5 + ┘ + + <span class='Function'>∾</span><span class='Modifier'>¨˝</span> <span class='Value'>tab</span> ⟨ ⟨ 1 0 1 4 3 ⟩ ⟨ 0 1 2 0 4 ⟩ ⟨ 1 2 3 1 5 ⟩ ⟩ </pre> -<p>This kind of reduction has an interesting property that the other two lack: it always removes exacly one axis, so that the result's shape is the argument's major cell shape. When applied to a later axis using the Rank or Cells modifier, it removes that axis instead.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omiIOKIvsKoy50g4oaVNOKAvzLigL8zICAgIyBSZWR1Y2Ugb3V0IHRoZSBmaXJzdCBheGlzCuKJoiDiiL7CqMudy5gg4oaVNOKAvzLigL8zICAjIFJlZHVjZSBvdXQgdGhlIHNlY29uZA==">↗️</a><pre> <span class='Function'>≢</span> <span class='Function'>∾</span><span class='Modifier'>¨˝</span> <span class='Function'>↕</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span> <span class='Comment'># Reduce out the first axis +<p>This kind of reduction has an interesting property not found in <code><span class='Modifier'>´</span></code> or <code><span class='Modifier'>˝</span></code>: it always removes exactly one axis, so that the result's shape is <code><span class='Value'>𝕩</span></code>'s major cell shape. When applied to a later axis using <a href="rank.html">Rank or Cells</a>, it removes that axis instead.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4omiIOKIvsKoy50gIOKGlTTigL8y4oC/MyAgIyBSZWR1Y2Ugb3V0IHRoZSBmaXJzdCBheGlzCuKJoiDiiL7CqMudy5gg4oaVNOKAvzLigL8zICAjIFJlZHVjZSBvdXQgdGhlIHNlY29uZA==">↗️</a><pre> <span class='Function'>≢</span> <span class='Function'>∾</span><span class='Modifier'>¨˝</span> <span class='Function'>↕</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span> <span class='Comment'># Reduce out the first axis </span>⟨ 2 3 ⟩ <span class='Function'>≢</span> <span class='Function'>∾</span><span class='Modifier'>¨˝˘</span> <span class='Function'>↕</span><span class='Number'>4</span><span class='Ligature'>‿</span><span class='Number'>2</span><span class='Ligature'>‿</span><span class='Number'>3</span> <span class='Comment'># Reduce out the second </span>⟨ 4 3 ⟩ |
