diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-11 20:08:12 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-11 20:08:12 -0400 |
| commit | b6bcf214e638fd36ef7d76c9f573a84e6e016482 (patch) | |
| tree | a435e4f0afed7266b868798e51b792c4600fabe1 /docs/doc/train.html | |
| parent | 383298b70274c5ac22eb2100aad7f6cd8eeca02d (diff) | |
Nothing but edits yet again
Diffstat (limited to 'docs/doc/train.html')
| -rw-r--r-- | docs/doc/train.html | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/docs/doc/train.html b/docs/doc/train.html index d45742b0..61e253ea 100644 --- a/docs/doc/train.html +++ b/docs/doc/train.html @@ -5,7 +5,7 @@ </head> <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="function-trains"><a class="header" href="#function-trains">Function trains</a></h1> -<p>Trains are an important aspect of BQN's <a href="tacit.html">tacit</a> programming capabilities. In fact, a crucial one: with trains and the <a href="identity.html">identity functions</a> Left (<code><span class='Function'>⊣</span></code>) and Right (<code><span class='Function'>⊢</span></code>), a fully tacit program can express any explicit function whose body is a statement with <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> used only as arguments (that is, there are no assignments and <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> are not used in operands or lists. Functions with assignments may have too many variables active at once to be directly translated but can be emulated by constructing lists. But it's probably a bad idea). Without trains it isn't possible to have two different functions that each use both arguments to a dyadic function. With trains it's perfectly natural.</p> +<p>Trains are an important aspect of BQN's <a href="tacit.html">tacit</a> programming capabilities. In fact, a crucial one: with trains, the <a href="identity.html">identity functions</a> Left (<code><span class='Function'>⊣</span></code>) and Right (<code><span class='Function'>⊢</span></code>), and <a href="constant.html">Constant</a> (<code><span class='Modifier'>˙</span></code>), a fully tacit program can express any explicit function whose body is a statement with <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> used only as arguments (that is, there are no assignments and <code><span class='Value'>𝕨</span></code> and <code><span class='Value'>𝕩</span></code> are not used in operands or lists. Functions with assignments may have too many variables active at once to be directly translated but can be emulated by constructing lists. But it's probably a bad idea). Without trains it isn't possible to have two different functions that each use both arguments to a dyadic function. With trains it's perfectly natural.</p> <p>BQN's trains are the same as those of Dyalog APL, except that Dyalog is missing the minor convenience of BQN's <a href="expression.html#nothing">Nothing</a> (<code><span class='Nothing'>·</span></code>). There are many Dyalog-based documents and videos on trains you can view on the <a href="https://aplwiki.com/wiki/Train">APL Wiki</a>.</p> <h2 id="2-train-3-train"><a class="header" href="#2-train-3-train">2-train, 3-train</a></h2> <p>Trains are an adaptation of the mathematical convention that, for example, two functions <code><span class='Function'>F</span></code> and <code><span class='Function'>G</span></code> can be added to get a new function <code><span class='Function'>F+G</span></code> that applies as <code><span class='Paren'>(</span><span class='Function'>F+G</span><span class='Paren'>)(</span><span class='Value'>x</span><span class='Paren'>)</span> <span class='Function'>=</span> <span class='Function'>F</span><span class='Paren'>(</span><span class='Value'>x</span><span class='Paren'>)</span><span class='Function'>+G</span><span class='Paren'>(</span><span class='Value'>x</span><span class='Paren'>)</span></code>. With a little change to the syntax, we can do exactly this in BQN:</p> @@ -13,10 +13,10 @@ ⟨ 4 4 4 4 4 ⟩ </pre> <p>So given a list of the first few natural numbers, that <em>same</em> list <em>plus</em> its <em>reverse</em> gives a list of just one number repeated many times. I'm sure if I were <a href="https://en.wikipedia.org/wiki/Carl_Friedrich_Gauss#Anecdotes">Gauss</a> I'd be able to find some clever use for that fact. The mathematical convention extends to any central operator and any number of function arguments, which in BQN means we use any three functions, and call the train with a left argument as well—the only numbers of arguments BQN syntax allows are 1 and 2.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=NyAoK+KJjS0pIDI=">↗️</a><pre> <span class='Number'>7</span> <span class='Paren'>(</span><span class='Function'>+≍-</span><span class='Paren'>)</span> <span class='Number'>2</span> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=NyAoK+KLiC0pIDI=">↗️</a><pre> <span class='Number'>7</span> <span class='Paren'>(</span><span class='Function'>+⋈-</span><span class='Paren'>)</span> <span class='Number'>2</span> ⟨ 9 5 ⟩ </pre> -<p>Here <a href="couple.html">Couple</a> (<code><span class='Function'>≍</span></code>) is used to combine two units into a list, so we get seven plus and minus two. It's also possible to leave out the leftmost function of a train, or replace it with <code><span class='Nothing'>·</span></code>. In this case the function on the right is called, then the other function is called on its result—it's identical to the mathematical composition <code><span class='Modifier2'>∘</span></code>, which is also part of BQN.</p> +<p><a href="pair.html">Pair</a> (<code><span class='Function'>⋈</span></code>) makes a list from two values, so we get seven plus and minus two. It's also possible to leave out the leftmost function of a train, or replace it with <code><span class='Nothing'>·</span></code>. In this case the function on the right is called, then the other function is called on its result—it's identical to the mathematical <a href="compose.html">composition</a> <code><span class='Modifier2'>∘</span></code>, which is also part of BQN.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=KOKIvuKMvSkgImFiIuKAvyJjZGUi4oC/ImYiCijCt+KIvuKMvSkgImFiIuKAvyJjZGUi4oC/ImYiCuKIvuKImOKMvSAiYWIi4oC/ImNkZSLigL8iZiI=">↗️</a><pre> <span class='Paren'>(</span><span class='Function'>∾⌽</span><span class='Paren'>)</span> <span class='String'>"ab"</span><span class='Ligature'>‿</span><span class='String'>"cde"</span><span class='Ligature'>‿</span><span class='String'>"f"</span> "fcdeab" <span class='Paren'>(</span><span class='Nothing'>·</span><span class='Function'>∾⌽</span><span class='Paren'>)</span> <span class='String'>"ab"</span><span class='Ligature'>‿</span><span class='String'>"cde"</span><span class='Ligature'>‿</span><span class='String'>"f"</span> @@ -26,20 +26,20 @@ </pre> <p>The three functions <code><span class='Function'>∾⌽</span></code>, <code><span class='Nothing'>·</span><span class='Function'>∾⌽</span></code>, and <code><span class='Function'>∾</span><span class='Modifier2'>∘</span><span class='Function'>⌽</span></code> are completely identical: <a href="join.html#join">Join</a> of <a href="reverse.html">Reverse</a>. Why might we want <strong>three</strong> different ways to write the same thing? If we only want to define a function, there's hardly any difference. However, these three forms have different syntax, and might be easier or harder to use in different contexts. As we'll see, we can use <code><span class='Function'>∾</span><span class='Modifier2'>∘</span><span class='Function'>⌽</span></code> inside a train without parenthesizing it, and string <code><span class='Nothing'>·</span><span class='Function'>∾⌽</span></code> but not <code><span class='Function'>∾⌽</span></code> together with other trains. Let's look at how the train syntax extends to longer expressions.</p> <h2 id="longer-trains"><a class="header" href="#longer-trains">Longer trains</a></h2> -<p>Function application in trains, as in other contexts, shares the lowest precedence level with assignment. Modifiers and strands (with <code><span class='Ligature'>‿</span></code>) have higher precedence, so they are applied before forming any trains. Once this is done, an expression is a <em>subject expression</em> if it ends with a subject and a <em>function expression</em> if it ends with a function (there are also modifier expressions, which aren't relevant here). A train is any function expression with multiple functions or subjects in it: while we've seen examples with two or three functions, any number are allowed.</p> -<p>Subject expressions are the domain of "old-school" APL, and just apply one function after another to a subject, possibly assigning some of the results (that's the top-level picture—anything can still happen within parentheses). Subjects other than the first appear only as left arguments to functions, which means that two subjects can't appear next to each other because the one on the left would have no corresponding function. Here's an example from the compiler (at one point), with functions and assignments numbered in the order they are applied and their arguments marked with <code><span class='Function'>«»</span></code>, and a fully-parenthesized version shown below.</p> +<p>Function application in trains, as in other contexts, shares the lowest precedence level with assignment. Modifiers and strands (with <code><span class='Ligature'>‿</span></code>) have higher precedence, so they are applied before forming any trains. Once this is done, an expression is a <em>subject expression</em> if it ends with a subject and a <em>function expression</em> if it ends with a function (a lone modifier can also be an expression, which isn't either of these). A train is any function expression with multiple functions or subjects in it: while we've seen examples with two or three functions, any number are allowed.</p> +<p>Subject expressions are the domain of "old-school" APL, and just apply one function after another to a subject, possibly assigning some of the results (that's the top-level picture—anything can still happen within parentheses). Subjects other than the first appear only as left arguments to functions, which means that two subjects can't appear next to each other because the one on the left would have no corresponding function. Here's an example from BQN's compiler, with functions and assignments numbered in the order they are applied and their arguments marked with <code><span class='Function'>«»</span></code>, and a fully-parenthesized version shown below.</p> <pre><span class='Value'>cn</span><span class='Gets'>←</span><span class='Value'>pi</span><span class='Function'>∾</span><span class='Value'>lt</span><span class='Gets'>←</span><span class='Function'>/</span><span class='Value'>𝕩</span><span class='Function'>≥</span><span class='Value'>ci</span><span class='Gets'>←</span><span class='Value'>vi</span><span class='Function'>+</span><span class='Value'>nv</span> <span class='Function'>«</span><span class='Number'>6</span> <span class='Function'>«</span><span class='Number'>5</span> <span class='Function'>«</span><span class='Number'>43</span><span class='Function'>«</span><span class='Number'>2</span> <span class='Function'>«</span><span class='Number'>1</span> <span class='Function'>«</span><span class='Number'>0</span><span class='Function'>»</span> <span class='Value'>cn</span><span class='Gets'>←</span><span class='Paren'>(</span><span class='Value'>pi</span><span class='Function'>∾</span><span class='Paren'>(</span><span class='Value'>lt</span><span class='Gets'>←</span><span class='Paren'>(</span><span class='Function'>/</span><span class='Paren'>(</span><span class='Value'>𝕩</span><span class='Function'>≥</span><span class='Paren'>(</span><span class='Value'>ci</span><span class='Gets'>←</span><span class='Paren'>(</span><span class='Value'>vi</span><span class='Function'>+</span><span class='Value'>nv</span><span class='Paren'>))))))</span> </pre> -<p>Function expressions have related but different rules, driven by the central principle that functions can be used as "arguments". Because roles can no longer be used to distinguish functions from their arguments, every function is assumed to have two arguments unless there's nothing to the left of it, or an assignment. In trains, assignments can't appear in the middle, only at the left side after all the functions have been applied. Here's another example from the compiler. Remember that for our purposes <code><span class='Function'>⌈</span><span class='Modifier'>`</span></code> behaves as a single component.</p> +<p>Function expressions have related but different rules, driven by the central principle that functions can be used as "arguments". Because roles can no longer be used to distinguish functions from their arguments, every function is assumed to have two arguments unless there's nothing to the left of it, or an assignment. In trains, assignments can't appear in the middle, only at the left side apart from all the functions. Here's another example from the compiler. Remember that for our purposes <code><span class='Function'>⌈</span><span class='Modifier'>`</span></code> behaves as a single component.</p> <pre><span class='Function'>⊢></span><span class='Number'>¯1</span><span class='Function'>»⌈</span><span class='Modifier'>`</span> <span class='Function'>«</span><span class='Number'>1</span> <span class='Function'>«</span><span class='Number'>0</span><span class='Function'>»</span> <span class='Function'>⊢></span><span class='Paren'>(</span><span class='Number'>¯1</span><span class='Function'>»⌈</span><span class='Modifier'>`</span><span class='Paren'>)</span> </pre> -<p>In a train, arguments alternate strictly with combining functions between them. Arguments can be either functions or subjects, except for the rightmost one, which has to be a function to indicate that the expression is a train. Trains tend to be shorter than subject expressions partly because to keep track of this alternation in a train of all functions, you need to know where each function is relative to the end of the train (subjects like the <code><span class='Number'>¯1</span></code> above only occur as left arguments, so they can also serve as anchors).</p> +<p>In a train, arguments alternate strictly with combining functions between them. Arguments can be either functions or subjects, except for the rightmost one, which has to be a function to indicate that the expression is a train. Trains tend to be shorter than subject expressions partly because this rule leads to some difficulty when reading. To keep track of the alternation in a train of all functions, you need to know where each function is relative to the end of the train (subjects like the <code><span class='Number'>¯1</span></code> above only occur as left arguments, so they can also serve as anchors).</p> <h2 id="practice-training"><a class="header" href="#practice-training">Practice training</a></h2> <p>The train <code><span class='Function'>⊢></span><span class='Number'>¯1</span><span class='Function'>»⌈</span><span class='Modifier'>`</span></code> is actually a nice trick to get the result of <a href="selfcmp.html#mark-firsts">Mark Firsts</a> <code><span class='Function'>∊</span><span class='Value'>𝕩</span></code> given the result of <a href="selfcmp.html#classify">Classify</a> <code><span class='Function'>⊐</span><span class='Value'>𝕩</span></code>, without doing another search. Let's take a closer look, first by applying it mechanically. To do this, we apply each "argument" to the train's argument, and then combine them with the combining functions.</p> <pre><span class='Paren'>(</span><span class='Function'>⊢</span> <span class='Function'>></span> <span class='Number'>¯1</span> <span class='Function'>»</span> <span class='Function'>⌈</span><span class='Modifier'>`</span><span class='Paren'>)</span> <span class='Value'>𝕩</span> @@ -47,7 +47,7 @@ <span class='Value'>𝕩</span> <span class='Function'>></span> <span class='Number'>¯1</span> <span class='Function'>»</span> <span class='Function'>⌈</span><span class='Modifier'>`</span><span class='Value'>𝕩</span> </pre> <p>So—although not all trains simplify so much—this confusing train is just <code><span class='Brace'>{</span><span class='Value'>𝕩</span><span class='Function'>></span><span class='Number'>¯1</span><span class='Function'>»⌈</span><span class='Modifier'>`</span><span class='Value'>𝕩</span><span class='Brace'>}</span></code>! Why would I write it in such an obtuse way? To someone used to working with trains, the function <code><span class='Paren'>(</span><span class='Function'>⊢></span><span class='Number'>¯1</span><span class='Function'>»⌈</span><span class='Modifier'>`</span><span class='Paren'>)</span></code> isn't any more complicated to read: <code><span class='Function'>⊢</span></code> in an argument position of a train just means <code><span class='Value'>𝕩</span></code> while <code><span class='Function'>⌈</span><span class='Modifier'>`</span></code> will be applied to the arguments. Using the train just means slightly shorter code and two fewer <code><span class='Value'>𝕩</span></code>s to trip over.</p> -<p>This function's argument is Classify (<code><span class='Function'>⊐</span></code>) of some list (in fact this technique also works on the <a href="search.html#index-of">index-of</a>-self <code><span class='Value'>𝕩</span><span class='Function'>⊐</span><span class='Value'>𝕩</span></code>). Classify moves along its argument, giving each major cell a number: the first unused natural number if that value hasn't been seen yet, and otherwise the number chosen when it was first seen. It can be implemented as <code><span class='Function'>⍷⊐⊢</span></code>, another train!</p> +<p>This function's argument is Classify (<code><span class='Function'>⊐</span></code>) of some list (in fact this technique also works on the <a href="search.html#index-of">index-of</a>-self <code><span class='Value'>𝕩</span><span class='Function'>⊐</span><span class='Value'>𝕩</span></code>). Classify moves along its argument, giving each major cell a number: the first unused natural number if that value hasn't been seen yet, and otherwise the number chosen when it was first seen. It can in turn be implemented as <code><span class='Function'>⍷⊐⊢</span></code>, another train!</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4oqiIHNjIOKGkCDiipAgInRhY2l0dHJhaW5zIg==">↗️</a><pre> <span class='Function'>⊢</span> <span class='Value'>sc</span> <span class='Gets'>←</span> <span class='Function'>⊐</span> <span class='String'>"tacittrains"</span> ⟨ 0 1 2 3 0 0 4 1 3 5 6 ⟩ </pre> @@ -76,19 +76,19 @@ <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=4o234oinfCAz4oC/NOKAv8KvM+KAv8KvMuKAvzA=">↗️</a><pre> <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'>¯3</span><span class='Ligature'>‿</span><span class='Number'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ </pre> -<p>If it doesn't have to be a function, it's easiest to write it all out! Let's assume we want a tacit function instead. With three one-argument functions, we can't use a 3-train, as the middle function in a 3-train always has two arguments. Instead, we will compose the functions with 2-trains. Composition is associative, meaning that this can be done starting at either the left or the right.</p> +<p>If it doesn't have to be a function, that's easiest to write it out! Let's assume we want a tacit function instead. With three one-argument functions, we can't use a 3-train, as the middle function in a 3-train always has two arguments. Instead, we will compose the functions with 2-trains. Composition is associative, meaning that this can be done starting at either the left or the right.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=KCjijbfiiKcpfCkgM+KAvzTigL/CrzPigL/CrzLigL8wCijijbco4oinfCkpIDPigL804oC/wq8z4oC/wq8y4oC/MA==">↗️</a><pre> <span class='Paren'>((</span><span class='Function'>⍷∧</span><span class='Paren'>)</span><span class='Function'>|</span><span class='Paren'>)</span> <span class='Number'>3</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'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ <span class='Paren'>(</span><span class='Function'>⍷</span><span class='Paren'>(</span><span class='Function'>∧|</span><span class='Paren'>))</span> <span class='Number'>3</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'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ </pre> -<p>We might make the first train above easier to read by using Atop (<code><span class='Modifier2'>∘</span></code>) instead of a 2-train. Atop is a 2-modifier, so it doesn't need parentheses when used in a train. The second train can also be changed to <code><span class='Function'>⍷∧</span><span class='Modifier2'>∘</span><span class='Function'>|</span></code> in the same way, but there is another option: the rightmost train <code><span class='Function'>∧|</span></code> can be expanded to <code><span class='Nothing'>·</span><span class='Function'>∧|</span></code>. After this it's an odd-length train in the last position, and doesn't need parentheses anymore.</p> +<p>We might make the first train above easier to read by using <a href="compose.html#atop">Atop</a> (<code><span class='Modifier2'>∘</span></code>) instead of a 2-train. Atop is a 2-modifier, so it doesn't need parentheses when used in a train. The second train can also be changed to <code><span class='Function'>⍷∧</span><span class='Modifier2'>∘</span><span class='Function'>|</span></code> in the same way, but there is another option: the rightmost train <code><span class='Function'>∧|</span></code> can be expanded to <code><span class='Nothing'>·</span><span class='Function'>∧|</span></code>. After this it's an odd-length train in the last position, and doesn't need parentheses anymore.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=KOKNt+KImOKIp3wpIDPigL804oC/wq8z4oC/wq8y4oC/MAoo4o23wrfiiKd8KSAz4oC/NOKAv8KvM+KAv8KvMuKAvzA=">↗️</a><pre> <span class='Paren'>(</span><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧|</span><span class='Paren'>)</span> <span class='Number'>3</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'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ <span class='Paren'>(</span><span class='Function'>⍷</span><span class='Nothing'>·</span><span class='Function'>∧|</span><span class='Paren'>)</span> <span class='Number'>3</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'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ </pre> -<p>These two forms have a different emphasis, because the first breaks into subfunctions <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧</span></code> and <code><span class='Function'>|</span></code> and the second into <code><span class='Function'>⍷</span></code> and <code><span class='Function'>∧|</span></code>. It's more common to use <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧</span></code> as a unit than <code><span class='Function'>∧|</span></code>, so in this case <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧|</span></code> is probably the better train.</p> +<p>These two forms have a different emphasis, because the first breaks into subfunctions <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧</span></code> and <code><span class='Function'>|</span></code> and the second into <code><span class='Function'>⍷</span></code> and <code><span class='Function'>∧|</span></code>. It's more common to use <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧</span></code> together than <code><span class='Function'>∧|</span></code>, so in this case <code><span class='Function'>⍷</span><span class='Modifier2'>∘</span><span class='Function'>∧|</span></code> is probably the better train.</p> <p>Many one-argument functions strung together is <a href="../commentary/problems.html#trains-dont-like-monads">a major weakness</a> for train syntax. If there are many such functions it's probably best to stick with a block function instead!</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=e+KNt+KIp3zwnZWpfSAz4oC/NOKAv8KvM+KAv8KvMuKAvzA=">↗️</a><pre> <span class='Brace'>{</span><span class='Function'>⍷∧|</span><span class='Value'>𝕩</span><span class='Brace'>}</span> <span class='Number'>3</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'>¯2</span><span class='Ligature'>‿</span><span class='Number'>0</span> ⟨ 0 2 3 4 ⟩ |
