diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-26 21:00:25 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2022-06-26 21:00:25 -0400 |
| commit | b6185d5029e2adcc721c0cc2097f591d9a09f135 (patch) | |
| tree | bf777353ed2a9b28d8b1577c5f36b68605240375 /docs/doc/block.html | |
| parent | c618ade174cc2b4e428457751ad8dd01130c2239 (diff) | |
I am in editing stepped in so far that, should I wade no more, returning were as tedious as go o'er.
Diffstat (limited to 'docs/doc/block.html')
| -rw-r--r-- | docs/doc/block.html | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/docs/doc/block.html b/docs/doc/block.html index 31f59aed..a79791df 100644 --- a/docs/doc/block.html +++ b/docs/doc/block.html @@ -5,14 +5,15 @@ </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="blocks"><a class="header" href="#blocks">Blocks</a></h1> -<p>In BQN, a <em>block</em> is any piece of code surrounded with curly braces <code><span class='Brace'>{}</span></code>. Blocks can be used simply to group statements, or can define functions or modifiers. They are the sole large-scale structure used to organize programs. An important aspect of organization is <a href="namespace.html">namespaces</a>, which are created with blocks but not discussed on this page.</p> +<p>In BQN, a <em>block</em> is any piece of code surrounded with curly braces <code><span class='Brace'>{}</span></code>. Blocks can be used simply to group statements, or can define functions or modifiers. They are the sole large-scale structure used to organize programs. One organizing tool not discussed here is <a href="namespace.html">namespaces</a>, which are created with blocks but have their own page. Programming without blocks (only recommended at the small scale) is called <a href="tacit.html">tacit</a> programming.</p> <p>Blocks are most commonly used to define functions by including one of the special names for arguments, <code><span class='Value'>π¨</span></code> or <code><span class='Value'>π©</span></code>. With the operands <code><span class='Function'>π½</span></code> or <code><span class='Function'>πΎ</span></code>, they can also define 1-modifiers or 2-modifiers.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=e/CdlakrMX0gMwrDl3vwnZWp8J2UvfCdlal9IDQ=">βοΈ</a><pre> <span class='Brace'>{</span><span class='Value'>π©</span><span class='Function'>+</span><span class='Number'>1</span><span class='Brace'>}</span> <span class='Number'>3</span> 4 <span class='Function'>Γ</span><span class='Brace'>{</span><span class='Value'>π©</span><span class='Function'>π½</span><span class='Value'>π©</span><span class='Brace'>}</span> <span class='Number'>4</span> 16 </pre> -<p>Because they use <a href="lexical.html">lexical scoping</a>, blocks can also be used to encapsulate code. If a block uses only variables that it initializes, then it has no dependence on its environment and would work the same way if defined anywhere. But it can also use external variables, defined in a containing block.</p> +<p>A block <a href="#block-headers">header</a> is written before a <code><span class='Head'>:</span></code> and describes the block type, and what inputs it accepts. A block can be split into <a href="#multiple-bodies">multiple bodies</a> using <code><span class='Head'>;</span></code>s, so that each handles different cases. A <a href="#predicates">predicate</a>, written with <code><span class='Head'>?</span></code>, can test an arbitrary condition to refine these cases.</p> +<p>Because they use <a href="lexical.html">lexical scoping</a>, blocks also encapsulate code. If a block uses only variables that it initializes, then it has no dependence on its environment and would work the same way if defined anywhere. But it can also use external variables, defined in a containing block.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=YeKGkGLihpAib3V0ZXIiCnsgYeKGkCJpbm5lciIg4ouEIGHigL9iIH0=">βοΈ</a><pre> <span class='Value'>a</span><span class='Gets'>β</span><span class='Value'>b</span><span class='Gets'>β</span><span class='String'>"outer"</span> <span class='Brace'>{</span> <span class='Value'>a</span><span class='Gets'>β</span><span class='String'>"inner"</span> <span class='Separator'>β</span> <span class='Value'>a</span><span class='Ligature'>βΏ</span><span class='Value'>b</span> <span class='Brace'>}</span> β¨ "inner" "outer" β© @@ -23,7 +24,7 @@ <span class='Value'>updown</span> β¨ 0 1 2 3 4 4 3 2 1 0 β© </pre> -<p>An immediate block is only ever evaluated once, and can't be used for control flow in a program. Including special names in a headerless block lets us define functions and modifiers, which have a broader range of uses. All special names are listed below:</p> +<p>An immediate block is only ever evaluated once, and can't be used for control flow in a program. Special names can be used to define <a href="ops.html">functions and modifiers</a>, which have a broader range of uses. All special names are listed below:</p> <table> <thead> <tr> @@ -65,14 +66,16 @@ </tr> </tbody> </table> -<p>Of these, <code><span class='Value'>π£</span></code> is sort of a "more special" character, as we'll discuss below. Except for <code><span class='Value'>π£</span></code>, every special name is a single character and can't have underscores added to spell it as a modifier. This allows a modifier to be applied to a special name with no spacing, as in <code><span class='Value'>π</span><span class='Modifier'>_m</span></code>, where it couldn't be with ordinary names.</p> +<p>Most special names have a lowercase form for a subject <a href="expression.html#syntactic-role">role</a> and uppercase for a function role. But <code><span class='Value'>π£</span></code> is sort of a "more special" character, as we'll discuss below. The special names other than <code><span class='Value'>π£</span></code> are single characters that don't attach to other letters, allowing <code><span class='Function'>π½</span><span class='Value'>π©</span></code> or <code><span class='Value'>π</span><span class='Modifier'>_m</span></code> to work without spaces; <code><span class='Value'>π£</span></code> is always modifier-valued, so it ought to attach to underscores.</p> <h3 id="arguments"><a class="header" href="#arguments">Arguments</a></h3> <p>The names <code><span class='Value'>π¨</span></code> and <code><span class='Value'>π©</span></code>, and their uppercase spellings, represent function arguments. As the argument to a function is typically data, it's more common to use the lowercase forms for these. Having either of these names turns an immediate block into a function (or an immediate modifier into a deferred one; see the next section). Instead of being evaluated as soon as it appears in the source, a function is evaluated when it's called, with the special names set to appropriate values. Their values can be changed like ordinary variables.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eydjJz3wnZWpfSAiYWJjZCIKeyDwnZWpK+KGqTIg4ouEIDDiiY3wnZWpIH0gMwo0IHsg4p+o8J2VqeKLhC3wnZWo4p+pIH0gNQ==">βοΈ</a><pre> <span class='Brace'>{</span><span class='String'>'c'</span><span class='Function'>=</span><span class='Value'>π©</span><span class='Brace'>}</span> <span class='String'>"abcd"</span> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eydjJz3wnZWpfSAiYWJjZCIKCnsg8J2VqSvihqkyIOKLhCAw4omN8J2VqSB9IDMKCjQgeyDin6jwnZWpLC3wnZWo4p+pIH0gNQ==">βοΈ</a><pre> <span class='Brace'>{</span><span class='String'>'c'</span><span class='Function'>=</span><span class='Value'>π©</span><span class='Brace'>}</span> <span class='String'>"abcd"</span> β¨ 0 0 1 0 β© + <span class='Brace'>{</span> <span class='Value'>π©</span><span class='Function'>+</span><span class='Gets'>β©</span><span class='Number'>2</span> <span class='Separator'>β</span> <span class='Number'>0</span><span class='Function'>β</span><span class='Value'>π©</span> <span class='Brace'>}</span> <span class='Number'>3</span> β¨ 0 5 β© - <span class='Number'>4</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Value'>π©</span><span class='Separator'>β</span><span class='Function'>-</span><span class='Value'>π¨</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> <span class='Number'>5</span> + + <span class='Number'>4</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Value'>π©</span><span class='Separator'>,</span><span class='Function'>-</span><span class='Value'>π¨</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> <span class='Number'>5</span> β¨ 5 Β―4 β© </pre> <p>A function with <code><span class='Value'>π¨</span></code> in its definition doesn't have to be called with two arguments. If it has only one, then <code><span class='Value'>π¨</span></code> is given the special value <a href="expression.html#nothing">Nothing</a>, or <code><span class='Nothing'>Β·</span></code>. This is the only time a variable can ever be Nothing, as an assignment such as <code><span class='Value'>v</span><span class='Gets'>β</span><span class='Nothing'>Β·</span></code> is not allowed.</p> @@ -81,7 +84,7 @@ <span class='Brace'>{</span> <span class='Paren'>(</span><span class='Number'>2</span><span class='Function'>Γ</span><span class='Value'>π¨</span><span class='Paren'>)</span><span class='Function'>-</span><span class='Value'>π©</span> <span class='Brace'>}</span> <span class='Number'>1</span> Β―1 </pre> -<p>In the second function, <code><span class='Value'>π¨</span></code> behaves just like <code><span class='Nothing'>Β·</span></code>, so that the function <code><span class='Number'>2</span><span class='Function'>Γ</span><span class='Value'>π¨</span></code> is not evaluated and <code><span class='Function'>-</span></code> doesn't have a left argument. It has a similar effect when used as the left argument to a function in a train.</p> +<p>In the second function, <code><span class='Value'>π¨</span></code> behaves just like <code><span class='Nothing'>Β·</span></code>, so that the function <code><span class='Number'>2</span><span class='Function'>Γ</span><span class='Value'>π¨</span></code> is not evaluated and <code><span class='Function'>-</span></code> doesn't have a left argument. It has a similar effect when used as the left argument to a function in a <a href="train.html">train</a>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=ImFiYyIgeyAo8J2VqOKJjeKMvSkg8J2VqSB9ICJkZWYiCiAgICAgIHsgKPCdlajiiY3ijL0pIPCdlakgfSAiZGVmIg==">βοΈ</a><pre> <span class='String'>"abc"</span> <span class='Brace'>{</span> <span class='Paren'>(</span><span class='Value'>π¨</span><span class='Function'>ββ½</span><span class='Paren'>)</span> <span class='Value'>π©</span> <span class='Brace'>}</span> <span class='String'>"def"</span> ββ β΅"abc @@ -92,7 +95,7 @@ β΅"fed" β </pre> -<p>However, <code><span class='Nothing'>Β·</span></code> can only be used as an argument, and not a list element or operand. Don't use <code><span class='Value'>π¨</span></code> in these ways in a function that could be called monadically. Another potential issue is that <code><span class='Modifier2'>βΈ</span></code> and <code><span class='Modifier2'>β</span></code> don't work the way you might expect.</p> +<p>However, <code><span class='Nothing'>Β·</span></code> can only be used as an argument, and not a list element or operand. Don't use <code><span class='Value'>π¨</span></code> in these ways in a function that could be called monadically. Another <a href="../problems.html#nothing--interacts-strangely-with-before-and-after">potential issue</a> is that <code><span class='Modifier2'>βΈ</span></code> and <code><span class='Modifier2'>β</span></code> don't work the way you might expect.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyDwnZWoIOKLhuKKuC0g8J2VqSB9IDU=">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Value'>π¨</span> <span class='Function'>β</span><span class='Modifier2'>βΈ</span><span class='Function'>-</span> <span class='Value'>π©</span> <span class='Brace'>}</span> <span class='Number'>5</span> 143.4131591025766 </pre> @@ -117,23 +120,23 @@ </pre> <p>The distinction between an immediate and deferred modifier only matters inside the braces. Once defined, the object is simply a modifier that can be called on operands to return a result. For a deferred modifier this result will always be a function; for an immediate modifier it could be anything.</p> <h3 id="self-reference"><a class="header" href="#self-reference">Self-reference</a></h3> -<p>If a block is assigned a name after it is created, this name can be used for recursion:</p> +<p>If a block is assigned a name after it's created, this name can be used for recursion:</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RmFjdCDihpAgeyDwnZWpIMOXICgw4oq4PCnil7Yx4oC/RmFjdCDwnZWpLTEgfQpGYWN0IDcKKMOXwrQxK+KGlSkgNyAgIyBUaGVyZSdzIG9mdGVuIGEgc2ltcGxlciBzb2x1dGlvbiB0aGFuIHJlY3Vyc2lvbg==">βοΈ</a><pre> <span class='Function'>Fact</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Value'>π©</span> <span class='Function'>Γ</span> <span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'><</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Function'>Fact</span> <span class='Value'>π©</span><span class='Function'>-</span><span class='Number'>1</span> <span class='Brace'>}</span> <span class='Function'>Fact</span> <span class='Number'>7</span> 5040 <span class='Paren'>(</span><span class='Function'>Γ</span><span class='Modifier'>Β΄</span><span class='Number'>1</span><span class='Function'>+β</span><span class='Paren'>)</span> <span class='Number'>7</span> <span class='Comment'># There's often a simpler solution than recursion </span>5040 </pre> -<p>This is somewhat unsatisfying because it is external to the function being defined, even though it doesn't depend on outside information. Instead, the special name <code><span class='Function'>π</span></code> can be used to refer to the function it appears in. This allows anonymous recursive functions to be defined.</p> +<p>This is somewhat unsatisfying because the name is external to the function being defined, but the definition shouldn't depend on outside information. Instead, the special name <code><span class='Function'>π</span></code> can be used to refer to the function it appears in. This allows anonymous recursive functions to be defined.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyDwnZWpIMOXICgw4oq4PCnil7Yx4oC/8J2ViiDwnZWpLTEgfSA3">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Value'>π©</span> <span class='Function'>Γ</span> <span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'><</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Function'>π</span> <span class='Value'>π©</span><span class='Function'>-</span><span class='Number'>1</span> <span class='Brace'>}</span> <span class='Number'>7</span> 5040 </pre> -<p>For modifiers, <code><span class='Value'>π£</span></code> refers to the containing modifier. <code><span class='Function'>π</span></code> makes the modifier a deferred modifier like <code><span class='Value'>π¨</span></code> and <code><span class='Value'>π©</span></code> do, and refers to the derived function. For example, this tail-recursive factorial function uses the operand to accumulate a result, a task that is usually done with a second <code><span class='Value'>factorial_helper</span></code> function in elementary Scheme.</p> +<p>For modifiers, <code><span class='Value'>π£</span></code> refers to the containing modifier. <code><span class='Function'>π</span></code> makes the modifier a deferred modifier like <code><span class='Value'>π¨</span></code> and <code><span class='Value'>π©</span></code> do, and refers to the derived function. For example, this tail-recursive factorial function uses the operand to accumulate a result, a task that's usually done with a second <code><span class='Value'>factorial_helper</span></code> function in elementary Scheme (BQN doesn't optimize tail recursion though; it's just shown here as an example).</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RmFjdF9tb2Qg4oaQIDEgeyAoMOKKuDwp4pe24p+o8J2VlywgKPCdlZfDl/CdlakpX/CdlaPin6kg8J2VqS0xIH0KRmFjdF9tb2QgNw==">βοΈ</a><pre> <span class='Function'>Fact_mod</span> <span class='Gets'>β</span> <span class='Number'>1</span> <span class='Brace'>{</span> <span class='Paren'>(</span><span class='Number'>0</span><span class='Modifier2'>βΈ</span><span class='Function'><</span><span class='Paren'>)</span><span class='Modifier2'>βΆ</span><span class='Bracket'>β¨</span><span class='Value'>π</span><span class='Separator'>,</span> <span class='Paren'>(</span><span class='Value'>π</span><span class='Function'>Γ</span><span class='Value'>π©</span><span class='Paren'>)</span><span class='Modifier'>_π£</span><span class='Bracket'>β©</span> <span class='Value'>π©</span><span class='Function'>-</span><span class='Number'>1</span> <span class='Brace'>}</span> <span class='Function'>Fact_mod</span> <span class='Number'>7</span> 5040 </pre> -<p>Because <code><span class='Value'>π£</span></code> only ever refers to a 1-modifier or 2-modifer, it can never make sense to refer to it as a function, and the uppercase letter <code><span class='Value'>β</span></code> is not recognized by BQN. In order to allow <code><span class='Value'>π£</span></code> to be spelled as a 1-modifier <code><span class='Modifier'>_π£</span></code> or 2-modifier <code><span class='Modifier2'>_π£_</span></code>, it is treated as an ordinary identifier character, so it must be separated from letters or numbers by spaces.</p> +<p>Because <code><span class='Value'>π£</span></code> only ever refers to a 1-modifier or 2-modifer, it can never make sense to refer to it as a function, and the uppercase letter <code><span class='Value'>β</span></code> is not recognized by BQN. To allow <code><span class='Value'>π£</span></code> to be spelled as a 1-modifier <code><span class='Modifier'>_π£</span></code> or 2-modifier <code><span class='Modifier2'>_π£_</span></code>, it's tokenized as an ordinary identifier character, so it has to be separated from adjacent letters or numbers with a space.</p> <h2 id="block-headers"><a class="header" href="#block-headers">Block headers</a></h2> <p>As a program becomes larger, it often becomes necessary to name inputs to blocks rather than just using special names. It can also become difficult to identify what kind of block is being defined, as it requires scanning through the block for special names. A <em>block header</em>, which is separated from the body of a block by a colon <code><span class='Head'>:</span></code>, specifies the kind of block and can declare names for the block and its inputs.</p> <pre><span class='Function'>Fact</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>F</span> <span class='Value'>n</span><span class='Head'>:</span> @@ -157,20 +160,21 @@ </span><span class='Brace'>{</span> <span class='Function'>F</span> <span class='Modifier2'>_op_</span> <span class='Nothing'>Β·</span><span class='Ligature'>βΏ</span><span class='Value'>val</span><span class='Head'>:</span> <span class='Value'>β¦</span> </pre> -<p>In all cases special names still work just like in a headerless function. In this respect the effect of the header is the same as a series of assignments at the beginning of a function, such as the following translation of the second header above:</p> +<p>In all cases special names still work just like in a headerless function. In this respect, the effect of the header is the same as a series of assignments at the beginning of a function, such as the following translation of the second header above:</p> <pre><span class='Brace'>{</span> <span class='Comment'># Fn _apply β¨a,bβ©: </span> <span class='Function'>Fn</span> <span class='Gets'>β</span> <span class='Function'>π½</span> <span class='Modifier'>_apply</span> <span class='Gets'>β</span> <span class='Modifier'>_π£</span> <span class='Bracket'>β¨</span><span class='Value'>a</span><span class='Separator'>,</span><span class='Value'>b</span><span class='Bracket'>β©</span> <span class='Gets'>β</span> <span class='Value'>π©</span> <span class='Value'>β¦</span> </pre> -<p>Unlike these assignments, the header also constrains what inputs the block can take: a monadic 1-modifier like the one above can't take a right operand or left argument, and consequently its body can't contain <code><span class='Function'>πΎ</span></code> or <code><span class='Value'>π¨</span></code>. Calling it with a left argument, or a right argument that isn't a two-element list, will result in an error.</p> +<p>Unlike these assignments, the header also constrains what inputs the block can take: a monadic 1-modifier like the one above can't take a right operand or left argument, so its body can't contain <code><span class='Function'>πΎ</span></code> or <code><span class='Value'>π¨</span></code>. Calling it with a left argument, or a right argument that isn't a two-element list, will result in an error.</p> <h3 id="destructuring"><a class="header" href="#destructuring">Destructuring</a></h3> -<p>Arguments and operands allow <a href="expression.html#destructuring">destructuring</a> like assignment does. While assignment only tolerates lists of variables, header destructuring also allows constants. The argument must match the given structure, including the constants where they appear, or an error results.</p> +<p>Arguments and operands allow <a href="expression.html#destructuring">destructuring</a> like assignment does. While assignment only tolerates lists of variables, header destructuring also allows constants. For the header to match, the argument must share the given structure, including the constants where they appear.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=RGVzdHJ1Y3Qg4oaQIHsg8J2ViiBh4oC/MeKAv+KfqGIswrcsMuKfqTogYeKJjWIgfQpEZXN0cnVjdCAgICAgICA14oC/MeKAv+KfqDcsz4AsMuKfqQ==">βοΈ</a><pre> <span class='Function'>Destruct</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>π</span> <span class='Value'>a</span><span class='Ligature'>βΏ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Bracket'>β¨</span><span class='Value'>b</span><span class='Separator'>,</span><span class='Nothing'>Β·</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Bracket'>β©</span><span class='Head'>:</span> <span class='Value'>a</span><span class='Function'>β</span><span class='Value'>b</span> <span class='Brace'>}</span> <span class='Function'>Destruct</span> <span class='Number'>5</span><span class='Ligature'>βΏ</span><span class='Number'>1</span><span class='Ligature'>βΏ</span><span class='Bracket'>β¨</span><span class='Number'>7</span><span class='Separator'>,</span><span class='Number'>Ο</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Bracket'>β©</span> β¨ 5 7 β© </pre> +<p>It's also worth noting here that <code><span class='Bracket'>[]</span></code> is a valid destructuring target, matching any length-0 array, even though it can't be used as a value since it's ambiguous. This syntax is also allowed in regular destructuring, but it's not very useful in that case.</p> <h3 id="special-names-in-headers"><a class="header" href="#special-names-in-headers">Special names in headers</a></h3> <p>Any element of a function or modifier header can be left nameless by using the corresponding special name in that position, instead of an identifier. For example, the header <code><span class='Value'>π¨</span> <span class='Function'>π½</span><span class='Modifier2'>_π£_</span><span class='Function'>πΎ</span> <span class='Value'>π©</span><span class='Head'>:</span></code> incorporates as much vagueness as possible. It indicates a deferred 2-modifier, but provides no other information.</p> <p>The name <code><span class='Value'>π¨</span></code> in this context can refer to either a left argument or no left argument, allowing a header with arguments to be used even for an ambiguous function. Recall that <code><span class='Value'>π¨</span></code> is the only token other than <code><span class='Nothing'>Β·</span></code> that can have no value. If an identifier or list is given as the left argument, then the function must be called with a left argument.</p> @@ -181,21 +185,26 @@ </span><span class='Brace'>{</span> <span class='Modifier'>_π£</span><span class='Head'>:</span> <span class='Comment'># 1-Modifier </span><span class='Brace'>{</span> <span class='Modifier2'>_π£_</span><span class='Head'>:</span> <span class='Comment'># 2-Modifier </span></pre> -<p>For immediate blocks, this is the only type of header possible, and it must use an identifier as there is no applicable special name. However, the name can't be used in code: it doesn't make sense to refer to a value while it is still being computed!</p> +<p>For immediate blocks, this is the only type of header possible, and it must use an identifier as there's no applicable special name. However, the name can't be used in code: it doesn't make sense to refer to a value while it's still being computed!</p> <h2 id="multiple-bodies"><a class="header" href="#multiple-bodies">Multiple bodies</a></h2> -<p>Blocks can include more than one body, separated by semicolons <code><span class='Head'>;</span></code>. The body used for a particular evaluation is chosen based on the arguments the the block. One special case is that functions and deferred modifiers can have two headerless bodies (that is, no headers or predicatesβsee below): the first applies when there's one argument and the second when there are two.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=QW1iaXYg4oaQIHsg4p+oMSzwnZWp4p+pIDsg4p+oMizwnZWoLPCdlanin6kgfQpBbWJpdiAnYScKJ2EnIEFtYml2ICdiJw==">βοΈ</a><pre> <span class='Function'>Ambiv</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Bracket'>β¨</span><span class='Number'>2</span><span class='Separator'>,</span><span class='Value'>π¨</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> +<p>Blocks can include more than one body, separated by semicolons <code><span class='Head'>;</span></code>. The body used for a particular evaluation is chosen based on the inputs to the block. One special case is that functions and deferred modifiers can have two headerless bodies (that is, no headers or <a href="#predicates">predicates</a>): the first applies when there's one argument and the second when there are two.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=QW1iaXYg4oaQIHsg4p+oMSzwnZWp4p+pIDsg4p+oMizwnZWoLPCdlanin6kgfQoKQW1iaXYgJ2EnCgonYScgQW1iaXYgJ2In">βοΈ</a><pre> <span class='Function'>Ambiv</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Bracket'>β¨</span><span class='Number'>2</span><span class='Separator'>,</span><span class='Value'>π¨</span><span class='Separator'>,</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Brace'>}</span> + <span class='Function'>Ambiv</span> <span class='String'>'a'</span> β¨ 1 'a' β© + <span class='String'>'a'</span> <span class='Function'>Ambiv</span> <span class='String'>'b'</span> β¨ 2 'a' 'b' β© </pre> <p>Bodies with headers come before any that don't have them. When a block is called, its headers are checked in order for compatibility with the arguments, and the first body with a compatible header is used.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2FzZUFkZCDihpAgeyAy8J2VijM6MOKAvzUgOyAy8J2VivCdlak64p+oMSwyK/Cdlanin6kgOyDwnZWK8J2VqToy4oC/8J2VqSB9CjIgQ2FzZUFkZCAzCjIgQ2FzZUFkZCA0CiAgQ2FzZUFkZCA0">βοΈ</a><pre> <span class='Function'>CaseAdd</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Number'>3</span><span class='Head'>:</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>5</span> <span class='Head'>;</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Function'>+</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Value'>π©</span> <span class='Brace'>}</span> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2FzZUFkZCDihpAgeyAy8J2VijM6MOKAvzUgOyAy8J2VivCdlak64p+oMSwyK/Cdlanin6kgOyDwnZWK8J2VqToy4oC/8J2VqSB9CgoyIENhc2VBZGQgMwoKMiBDYXNlQWRkIDQKCiAgQ2FzZUFkZCA0">βοΈ</a><pre> <span class='Function'>CaseAdd</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Number'>3</span><span class='Head'>:</span><span class='Number'>0</span><span class='Ligature'>βΏ</span><span class='Number'>5</span> <span class='Head'>;</span> <span class='Number'>2</span><span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>2</span><span class='Function'>+</span><span class='Value'>π©</span><span class='Bracket'>β©</span> <span class='Head'>;</span> <span class='Function'>π</span><span class='Value'>π©</span><span class='Head'>:</span><span class='Number'>2</span><span class='Ligature'>βΏ</span><span class='Value'>π©</span> <span class='Brace'>}</span> + <span class='Number'>2</span> <span class='Function'>CaseAdd</span> <span class='Number'>3</span> β¨ 0 5 β© + <span class='Number'>2</span> <span class='Function'>CaseAdd</span> <span class='Number'>4</span> β¨ 1 6 β© + <span class='Function'>CaseAdd</span> <span class='Number'>4</span> β¨ 2 4 β© </pre> @@ -214,21 +223,24 @@ </pre> <p>These case-style headers function exactly the same as if they were preceded by <code><span class='Function'>π</span></code>, and can be mixed with other kinds of headers.</p> <h3 id="predicates"><a class="header" href="#predicates">Predicates</a></h3> -<p>Destructuring with a header is quite limited, only allowing matching structure and data with exact equality. A predicate, written with <code><span class='Head'>?</span></code>, allows you to test an arbitrary property before evaluating the rest of the body, and also serves as a limited kind of control flow. It can be thought of as an extension to a header, so that for example the following function requires the argument to have two elements and for the first to be less than the second before using the first body. Otherwise it moves to the next body, which is unconditional.</p> -<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2hlY2tQYWlyIOKGkCB7IPCdlYrin6hhLGLin6k6IGE8Yj8gIm9rIiA7ICJub3Qgb2siIH0KCkNoZWNrUGFpciDin6gzLDjin6kgICAgIyBGYWlscyBkZXN0cnVjdHVyaW5nCkNoZWNrUGFpciDin6gxLDQsNeKfqSAgIyBOb3QgYSBwYWlyCkNoZWNrUGFpciDin6gzLMKvMeKfqSAgICMgTm90IGFzY2VuZGluZw==">βοΈ</a><pre> <span class='Function'>CheckPair</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>π</span><span class='Bracket'>β¨</span><span class='Value'>a</span><span class='Separator'>,</span><span class='Value'>b</span><span class='Bracket'>β©</span><span class='Head'>:</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span><span class='Head'>?</span> <span class='String'>"ok"</span> <span class='Head'>;</span> <span class='String'>"not ok"</span> <span class='Brace'>}</span> +<p>Destructuring with a header is limited, as it can only match a particular structure or value exactlyβnot, for example, a range of lengths. A predicate, written with <code><span class='Head'>?</span></code>, allows you to test an arbitrary property before evaluating the rest of the body, and also serves as a limited kind of control flow. It can be thought of as an extension to a header. So the following function requires the argument to have two elements and for the first to be less than the second before using the first body. Otherwise it moves to the next body, which is unconditional.</p> +<a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=Q2hlY2tQYWlyIOKGkCB7IPCdlYrin6hhLGLin6k6IGE8Yj8gIm9rIiA7ICJub3Qgb2siIH0KCkNoZWNrUGFpciDin6gzLDjin6kgICAgIyBGYWlscyBkZXN0cnVjdHVyaW5nCgpDaGVja1BhaXIg4p+oMSw0LDXin6kgICMgTm90IGEgcGFpcgoKQ2hlY2tQYWlyIOKfqDMswq8x4p+pICAgIyBOb3QgYXNjZW5kaW5n">βοΈ</a><pre> <span class='Function'>CheckPair</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Function'>π</span><span class='Bracket'>β¨</span><span class='Value'>a</span><span class='Separator'>,</span><span class='Value'>b</span><span class='Bracket'>β©</span><span class='Head'>:</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span><span class='Head'>?</span> <span class='String'>"ok"</span> <span class='Head'>;</span> <span class='String'>"not ok"</span> <span class='Brace'>}</span> <span class='Function'>CheckPair</span> <span class='Bracket'>β¨</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>8</span><span class='Bracket'>β©</span> <span class='Comment'># Fails destructuring </span>"ok" + <span class='Function'>CheckPair</span> <span class='Bracket'>β¨</span><span class='Number'>1</span><span class='Separator'>,</span><span class='Number'>4</span><span class='Separator'>,</span><span class='Number'>5</span><span class='Bracket'>β©</span> <span class='Comment'># Not a pair </span>"not ok" + <span class='Function'>CheckPair</span> <span class='Bracket'>β¨</span><span class='Number'>3</span><span class='Separator'>,</span><span class='Number'>Β―1</span><span class='Bracket'>β©</span> <span class='Comment'># Not ascending </span>"not ok" </pre> -<p>The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. In fact, <code><span class='Head'>?</span></code> functions just like a separator (like <code><span class='Separator'>β</span></code> or <code><span class='Separator'>,</span></code>) with a side effect.</p> +<p>The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. Really, <code><span class='Head'>?</span></code> works just like a separator (like <code><span class='Separator'>β</span></code> or <code><span class='Separator'>,</span></code>) with a side effect.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyBy4oaQ4oy98J2VqSDii4QgJ3QnPeKKkXIgPyByIDsg8J2VqSB9wqggInRlc3Qi4oC/InRoaXMi">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Value'>r</span><span class='Gets'>β</span><span class='Function'>β½</span><span class='Value'>π©</span> <span class='Separator'>β</span> <span class='String'>'t'</span><span class='Function'>=β</span><span class='Value'>r</span> <span class='Head'>?</span> <span class='Value'>r</span> <span class='Head'>;</span> <span class='Value'>π©</span> <span class='Brace'>}</span><span class='Modifier'>Β¨</span> <span class='String'>"test"</span><span class='Ligature'>βΏ</span><span class='String'>"this"</span> β¨ "tset" "this" β© </pre> -<p>So <code><span class='Value'>r</span></code> is the reversed argument, and if its first character (the last one in <code><span class='Value'>π©</span></code>) is <code><span class='String'>'t'</span></code> then it returns <code><span class='Value'>r</span></code>, and otherwise we abandon that line of reasoning and return <code><span class='Value'>π©</span></code>. This sounds a lot like an if statement. And <code><span class='Brace'>{</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span> <span class='Head'>?</span> <span class='Value'>a</span> <span class='Head'>;</span> <span class='Value'>b</span> <span class='Brace'>}</span></code>, which computes <code><span class='Value'>a</span><span class='Function'>β</span><span class='Value'>b</span></code> the hard way, shows how the syntax can be similar to a ternary operator. This is an immediate block with multiple bodies, something that makes sense with predicates but not headers. But <code><span class='Head'>?;</span></code> offers more possibilities. It can support any number of options, with multiple tests for each oneβthe structure below is "if _ and _ then _; else if _ then _; else _".</p> +<p>So <code><span class='Value'>r</span></code> is the reversed argument, and if its first character (the last one in <code><span class='Value'>π©</span></code>) is <code><span class='String'>'t'</span></code> then it returns <code><span class='Value'>r</span></code>, and otherwise we abandon that line of reasoning and return <code><span class='Value'>π©</span></code>.</p> +<p>This sounds a lot like an if statement. And <code><span class='Brace'>{</span> <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span> <span class='Head'>?</span> <span class='Value'>a</span> <span class='Head'>;</span> <span class='Value'>b</span> <span class='Brace'>}</span></code>, which computes <code><span class='Value'>a</span><span class='Function'>β</span><span class='Value'>b</span></code> the hard way, shows how the syntax can be similar to a ternary operator. This is an immediate block with multiple bodies, something that makes sense with predicates but not headers. But <code><span class='Head'>?;</span></code> offers more possibilities. It can support any number of options, with multiple tests for each oneβthe structure below is "if _ and _ then _; else if _ then _; else _".</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=VGhpbmcg4oaQIHsg8J2VqeKJpTM/IPCdlaniiaQ4PyAyfPCdlakgOyDwnZWpPTA/IEAgOyDiiJ4gfQoKKOKKoiDiiY0gVGhpbmfCqCkg4oaVMTAgICMgVGFibGUgb2YgYXJndW1lbnRzIGFuZCByZXN1bHRz">βοΈ</a><pre> <span class='Function'>Thing</span> <span class='Gets'>β</span> <span class='Brace'>{</span> <span class='Value'>π©</span><span class='Function'>β₯</span><span class='Number'>3</span><span class='Head'>?</span> <span class='Value'>π©</span><span class='Function'>β€</span><span class='Number'>8</span><span class='Head'>?</span> <span class='Number'>2</span><span class='Function'>|</span><span class='Value'>π©</span> <span class='Head'>;</span> <span class='Value'>π©</span><span class='Function'>=</span><span class='Number'>0</span><span class='Head'>?</span> <span class='String'>@</span> <span class='Head'>;</span> <span class='Number'>β</span> <span class='Brace'>}</span> <span class='Paren'>(</span><span class='Function'>β’</span> <span class='Function'>β</span> <span class='Function'>Thing</span><span class='Modifier'>Β¨</span><span class='Paren'>)</span> <span class='Function'>β</span><span class='Number'>10</span> <span class='Comment'># Table of arguments and results @@ -237,7 +249,7 @@ @ β β 1 0 1 0 1 0 β β </pre> -<p>This structure is still constrained by the rules of block bodies: each instance of <code><span class='Head'>;</span></code> is a separate scope, so that variables defined before a <code><span class='Head'>?</span></code> don't survive past the <code><span class='Head'>;</span></code>.</p> +<p>This structure is still controlled by the rules of block bodies: each instance of <code><span class='Head'>;</span></code> is a separate scope, so that variables defined before a <code><span class='Head'>?</span></code> don't survive past the <code><span class='Head'>;</span></code>.</p> <a class="replLink" title="Open in the REPL" target="_blank" href="https://mlochbaum.github.io/BQN/try.html#code=eyAwPW7ihpDiiaDwnZWpID8g4oieIDsgbiB9ICJhYmMi">βοΈ</a><pre> <span class='Brace'>{</span> <span class='Number'>0</span><span class='Function'>=</span><span class='Value'>n</span><span class='Gets'>β</span><span class='Function'>β </span><span class='Value'>π©</span> <span class='Head'>?</span> <span class='Number'>β</span> <span class='Head'>;</span> <span class='Value'>n</span> <span class='Brace'>}</span> <span class='String'>"abc"</span> <span class='Error'>Error: Undefined identifier</span> </pre> |
