diff options
| author | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-10-09 21:58:01 -0400 |
|---|---|---|
| committer | Marshall Lochbaum <mwlochbaum@gmail.com> | 2021-10-09 22:01:06 -0400 |
| commit | afc086a54b9f37acd4d90ff6cc607ab3008c78f9 (patch) | |
| tree | f37e312a60284a0f822a5bc0aaab028c57645a2b /doc/block.md | |
| parent | f2cd25f1ab2b04007c1f112dfffd3590e60f2d3b (diff) | |
Predicate documentation
Diffstat (limited to 'doc/block.md')
| -rw-r--r-- | doc/block.md | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/doc/block.md b/doc/block.md index 7270f302..27cb47ae 100644 --- a/doc/block.md +++ b/doc/block.md @@ -188,6 +188,32 @@ A special rule allows for convenient case-matching syntax for one-argument funct 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 + CheckPair β¨1,4,5β© # Not a pair + CheckPair β¨3,Β―1β© # Not ascending + +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" + +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 + +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" + +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.* |
