diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-09-28 22:06:16 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-09-28 22:06:21 -0400 |
| commit | a81f4712c41c03e51f2365f7ea794ad63bcb5411 (patch) | |
| tree | 9fef7b4c3b677c19808abeb0e3f86998863d021f /docs | |
| parent | 33276d7898340edef7fa456747f0f8e7b0af4b33 (diff) | |
Update control structures document with predicates
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/doc/control.html | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/docs/doc/control.html b/docs/doc/control.html index 10a9fc7a..ae1ce1e4 100644 --- a/docs/doc/control.html +++ b/docs/doc/control.html @@ -47,18 +47,22 @@ <span class='Value'>a</span> <span class='Function'>+</span><span class='Gets'>↩</span> <span class='Number'>10</span> <span class='Brace'>}</span> </pre> -<p>A final option is to use a <a href="block.html#returns">return</a> to exit a block early. This is really more of an "unless" statement; to get a proper "if" the condition needs to be negated. Repeat is still the easiest way to do the conditional logic, in this case deciding whether to return.</p> -<pre><span class='Brace'>{</span> - <span class='Function'>𝕊</span><span class='Gets'>→</span><span class='Modifier2'>⍟</span><span class='Paren'>(</span><span class='Function'>¬</span><span class='Value'>a</span><span class='Function'><</span><span class='Number'>10</span><span class='Paren'>)</span> <span class='String'>@</span> <span class='Comment'># Return @ unless a<10 -</span> <span class='Value'>a</span> <span class='Function'>+</span><span class='Gets'>↩</span> <span class='Number'>10</span> -<span class='Brace'>}</span> +<p>The result of any of these if statements is the result of the action if it's performed, and otherwise it's whatever argument was passed to the statement, which is <code><span class='String'>@</span></code> or <code><span class='Number'>10</span></code> here.</p> +<p>BQN's syntax for a pure if statement isn't so good, but predicates handle <a href="#if-else">if-else</a> statements nicely. So in most cases you'd forego the definitions above in favor of an if-else with nothing in the else branch:</p> +<pre><span class='Brace'>{</span> <span class='Value'>a</span><span class='Function'><</span><span class='Number'>10</span> <span class='Value'>?</span> <span class='Value'>a</span><span class='Function'>+</span><span class='Gets'>↩</span><span class='Number'>10</span> <span class='Value'>;</span> <span class='String'>@</span> <span class='Brace'>}</span> </pre> -<p>In all cases, the result of an if statement is the result of the action if it's performed, and otherwise it's whatever argument was passed to the statement, which is <code><span class='String'>@</span></code> in most examples above.</p> <h2 id="repeat"><a class="header" href="#repeat">Repeat</a></h2> <p>There's no reason the condition in an if statement from the previous section has to be boolean: it could be any natural number, causing the action to be repeated that many times. If the action is never performed, the result is the statement's argument, and otherwise it's the result of the last time the action was performed.</p> <p>Another option is to use a <a href="#for">for-each</a> statement with an argument of <code><span class='Function'>↕</span><span class='Value'>n</span></code>: in this case the result is the list of each action's result.</p> <h2 id="if-else"><a class="header" href="#if-else">If-Else</a></h2> -<p>Despite the name, an if-else statement is most closely related to a <a href="#switch-case">switch-case</a> statement: in fact, it's just a special case where the two cases are true (<code><span class='Number'>1</span></code>) and false (<code><span class='Number'>0</span></code>). As a result, we can implement it either with Choose (<code><span class='Modifier2'>◶</span></code>) or with <a href="block.html#case-headers">case headers</a> of <code><span class='Number'>1</span></code> and <code><span class='Number'>0</span></code>.</p> +<p>In most cases, the easy way to write an if-else statement is with predicates:</p> +<pre><span class='Brace'>{</span> + <span class='Value'>threshold</span> <span class='Function'><</span> <span class='Number'>6</span> <span class='Value'>?</span> + <span class='Value'>a</span> <span class='Gets'>↩</span> <span class='Function'>Small</span> <span class='Value'>threshold</span> <span class='Value'>;</span> <span class='Comment'># If predicate was true +</span> <span class='Value'>b</span> <span class='Gets'>↩</span> <span class='Number'>1</span> <span class='Function'>Large</span> <span class='Value'>threshold</span> <span class='Comment'># If it wasn't +</span><span class='Brace'>}</span> +</pre> +<p>We might also think of an if-else statement as a kind of <a href="#switch-case">switch-case</a> statement, where the two cases are true (<code><span class='Number'>1</span></code>) and false (<code><span class='Number'>0</span></code>). As a result, we can implement it either with Choose (<code><span class='Modifier2'>◶</span></code>) or with <a href="block.html#case-headers">case headers</a> of <code><span class='Number'>1</span></code> and <code><span class='Number'>0</span></code>.</p> <p>When using Choose, note that the natural ordering places the false case before the true one to match list index ordering. To get the typical if-else order, the condition should be negated or the statements reversed. Here's a function to get an if-else statement by swapping the conditions, and two ways its application might be written.</p> <pre><span class='Function'>IfElse</span> <span class='Gets'>←</span> <span class='Brace'>{</span><span class='Value'>cond</span><span class='Ligature'>‿</span><span class='Function'>True</span><span class='Ligature'>‿</span><span class='Function'>False</span><span class='Value'>:</span> <span class='Value'>cond</span><span class='Modifier2'>◶</span><span class='Function'>False</span><span class='Ligature'>‿</span><span class='Function'>True</span> <span class='String'>@</span><span class='Brace'>}</span> @@ -82,8 +86,14 @@ </pre> <p>The result of an if-else statement is just the result of whichever branch was used; chained if-else and switch-case statements will work the same way.</p> <h3 id="chained-if-else"><a class="header" href="#chained-if-else">Chained If-Else</a></h3> -<p>One pattern in imperative languages is to check one condition and apply an action if it succeeds, but check a different condition if it fails, in sequence until some condition succeeds or every one has been checked. Languages might make this pattern easier by making if-else right associative, so that the programmer can write an <code><span class='Value'>if</span></code> statement followed by a sequence of <code><span class='Value'>else</span> <span class='Value'>if</span></code> "statements", or might just provide a unified <code><span class='Value'>elif</span></code> keyword that works similarly (while this <em>is</em> a common pattern, I suspect it's used more often than it's really wanted because of this syntactic support).</p> -<p>In BQN it's possible to nest <code><span class='Function'>IfElse</span></code> expressions, but it's also possible to write a control structure that chains them all at one level. For this statement the input will be a sequence of <code><span class='Bracket'>⟨</span><span class='Function'>Test</span><span class='Separator'>,</span><span class='Function'>Action</span><span class='Bracket'>⟩</span></code> pairs, followed by a final action to perform if no test succeeds. The first test is always performed; other tests should be wrapped in blocks because otherwise they'll be executed even if an earlier test succeeded.</p> +<p>One pattern in imperative languages is to check one condition and apply an action if it succeeds, but check a different condition if it fails, in sequence until some condition succeeds or every one has been checked. Languages might make this pattern easier by making if-else right associative, so that the programmer can write an <code><span class='Value'>if</span></code> statement followed by a sequence of <code><span class='Value'>else</span> <span class='Value'>if</span></code> "statements", or might just provide a unified <code><span class='Value'>elif</span></code> keyword that works similarly. BQN's predicates work really well for this structure:</p> +<pre><span class='Brace'>{</span> + <span class='Value'>a</span><span class='Function'><</span><span class='Value'>b</span> <span class='Value'>?</span> <span class='Value'>a</span><span class='Function'>+</span><span class='Gets'>↩</span><span class='Number'>1</span> <span class='Value'>;</span> + <span class='Value'>a</span><span class='Function'><</span><span class='Value'>c</span> <span class='Value'>?</span> <span class='Value'>c</span><span class='Function'>-</span><span class='Gets'>↩</span><span class='Number'>1</span> <span class='Value'>;</span> + <span class='Value'>a</span><span class='Function'>-</span><span class='Gets'>↩</span><span class='Number'>2</span> +<span class='Brace'>}</span> +</pre> +<p>For a function-based approach, it's possible to nest <code><span class='Function'>IfElse</span></code> expressions, but it's also possible to write a control structure that chains them all at one level. For this statement the input will be a sequence of <code><span class='Bracket'>⟨</span><span class='Function'>Test</span><span class='Separator'>,</span><span class='Function'>Action</span><span class='Bracket'>⟩</span></code> pairs, followed by a final action to perform if no test succeeds. The first test is always performed; other tests should be wrapped in blocks because otherwise they'll be executed even if an earlier test succeeded.</p> <pre><span class='Function'>Test</span> <span class='Gets'>←</span> <span class='Brace'>{</span><span class='Value'>fn</span><span class='Gets'>←</span><span class='Brace'>{</span><span class='Function'>Cond</span><span class='Ligature'>‿</span><span class='Function'>Act</span> <span class='Function'>𝕊</span> <span class='Value'>else:</span> <span class='Function'>Cond</span><span class='Modifier2'>◶</span><span class='Function'>Else</span><span class='Ligature'>‿</span><span class='Function'>Act</span><span class='Brace'>}</span><span class='Modifier'>´</span><span class='Value'>𝕩</span> <span class='Separator'>⋄</span> <span class='Function'>Fn</span><span class='String'>@</span><span class='Brace'>}</span> <span class='Function'>Test</span> <span class='Bracket'>⟨</span> |
