From afc086a54b9f37acd4d90ff6cc607ab3008c78f9 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Sat, 9 Oct 2021 21:58:01 -0400 Subject: Predicate documentation --- docs/doc/block.html | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'docs/doc/block.html') diff --git a/docs/doc/block.html b/docs/doc/block.html index d3eb2bb8..9ae75ef7 100644 --- a/docs/doc/block.html +++ b/docs/doc/block.html @@ -213,6 +213,35 @@ ERROR }

These case-style headers function exactly the same as if they were preceded by π•Š, and can be mixed with other kinds of headers.

+

Predicates

+

Destructuring with a header is quite limited, only allowing matching structure and data with exact equality. A predicate, written with ?, 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 a single element and for that element to be less than zero before using the first body 1+𝕩. Otherwise it moves to the next one, an unconditional 𝕩.

+↗️
    CheckPair ← { π•ŠβŸ¨a,b⟩: a<b? "ok" ; "not ok" }
+
+    CheckPair ⟨3,8⟩    # Fails destructuring
+"ok"
+    CheckPair ⟨1,4,5⟩  # Not a pair
+"not ok"
+    CheckPair ⟨3,¯1⟩   # Not ascending
+"not ok"
+
+

The body where the predicate appears doesn't need to start with a header, and there can be other statements before it. In fact, ? functions just like a separator (like β‹„ or ,) with a side effect.

+↗️
    { rβ†βŒ½π•© β‹„ 't'=βŠ‘r ? r ; 𝕩 }Β¨ "test"β€Ώ"this"
+⟨ "tset" "this" ⟩
+
+

So r is the reversed argument, and if its first character (the last one in 𝕩) is 't' then it returns r, and otherwise we abandon that line of reasoning and return 𝕩. This sounds a lot like an if statement. And { a<b ? a ; b }, which computes a⌊b the hard way, shows how the syntax can be similar to a ternary operator. But ?; is more flexible than that. It can support any number of options, with multiple tests for each oneβ€”the structure below is "if _ and _ then _; else if _ then _; else _".

+↗️
    Thing ← { 𝕩β‰₯3? 𝕩≀8? 2|𝕩 ; 𝕩=0? @ ; ∞ }
+
+    (⊒ ≍ ThingΒ¨) ↕10  # Table of arguments and results
+β”Œβ”€                     
+β•΅ 0 1 2 3 4 5 6 7 8 9  
+  @ ∞ ∞ 1 0 1 0 1 0 ∞  
+                      β”˜
+
+

This structure is still constrained by the rules of block bodies: each instance of ; is a separate scope, so that variables defined before a ? don't survive past the ;.

+↗️
    { 0=n←≠𝕩 ? ∞ ; n } "abc"
+ERROR
+
+

This is the main drawback of predicates relative to guards in APL dfns (also written with ?), while the advantage is that it allows multiple expressions, or extra conditions, after a ?. It's not how I would have designed it if I just wanted to make a syntax for if statements, but it's a natural fit for the header system.

Returns

This feature is not yet included in any BQN implementation.

The glyph β†’ indicates an early return from a block. It must be preceded either by one of the self-reference special names π•Š or 𝕣 or by an internal name for a containing block. The combination of name and return tokenβ€”like Fβ†’, let's sayβ€”is a function that returns from the current instance of the indicated block. If that instance has already returned, then it instead results in an error.

-- cgit v1.2.3