*View this file with results and syntax highlighting [here](https://mlochbaum.github.io/BQN/doc/control.html).* # Control flow in BQN BQN does not have ALGOL-style control structures. Instead, functional techniques can be used to control when code is evaluated. This page describes how BQN functionality can be used to emulate something more familiar to an imperative programmer. Control structures here are always functions that act on lists of functions, although alternatives might be presented. This is because stranded functions can be formatted in a very similar way to blocks in curly-brace languages. However, there are many ways to write control flow, including simple operators and a mix of operators and more control-structure-like code. Implementing a control structure rarely takes much code with any method, so there are usually several simple ways to implement a given flow or a variation of it. The surfeit of ways to write control structures could be a bit of an issue for reading BQN. My hope is that the community can eventually settle on a smaller set of standard forms to recommend so that you won't have to recognize all the variants given here. On the other hand, the cost of using specialized control structures is lower in a large project without too many contributors. In this case BQN's flexibility allows developers to adapt to the project's particular demands (for example, some programs use switch/case statements heavily but most do not). The useful control structures introduced here are collected as shortened definitions below. `While` uses the slightly more complicated implementation that avoids stack overflow, and `DoWhile` and `For` are written in terms of it in order to share this property. The more direct versions with linear stack use appear in the main text. If ← {𝕏⍟𝕎@}´ # Also Repeat IfElse ← {c‿T‿F: c◶F‿T@} While ← {𝕩{𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}𝕨@}´ # While 1‿{... to run forever DoWhile ← {𝕏@ ⋄ While 𝕨‿𝕩}´ For ← {I‿C‿P‿A: I@ ⋄ While⟨C,P∘A⟩} # Switch/case statements have many variations; these are a few Match ← {𝕏𝕨}´ Select ← {(⊑𝕩)◶(1↓𝕩)@} Switch ← {c←⊑𝕩 ⋄ m‿a←<˘⍉∘‿2⥊1↓𝕩 ⋄ (⊑a⊐C)◶m@} Test ← {fn←{C‿A𝕊e:C◶A‿E}´𝕩⋄Fn@} ## Blocks and functions Control structures are generally defined to work with blocks of code, which they might skip, or execute one or more times. This might sound like a BQN immediate block, which also consists of a sequence of code to execute, but immediate blocks are always executed as soon as they are encountered and can't be manipulated the way that blocks in imperative languages can. They're intended to be used with [lexical scoping](lexical.md) as a tool for encapsulation. Instead, the main tool we will use to get control structures is the block function. Using functions as blocks is a little outside their intended purpose, and the fact that they have to be passed an argument and are expected to use it will be a minor annoyance. The following conventions signal a function that ignores its argument and is called purely for the side effects: - Pass `@` to a function that ignores its argument. It's a nice signal that nothing is happening and is easy to type. - A headerless function that doesn't use an argument will be interpreted as an immediate block by default. Start it with the line `𝕤` to avoid this (it's an instruction to navel gaze: the function contemplates its self, but does nothing about it). Other options like `𝕊:`, `F:`, or `𝕩` also work, but are more visually distracting. Even with these workarounds, BQN's "niladic" function syntax is quite lightweight, comparing favorably to a low-boilerplate language like Javascript. fn = ()=>{m+=1;n*=2}; fn() Fn ← {𝕤⋄ m+↩1,n×↩2}, Fn @ Control structures are called "statements" below to match common usage, but they are actually expressions, and return a value that might be used later. ## If The if statement conditionally performs some action. It is similar to the Repeat (`⍟`) modifier with a right operand returning a boolean: `Fn⍟Cond 𝕩` gives `Fn 𝕩` if `Cond 𝕩` is `1`, and returns `𝕩` without calling `Fn` if `Cond 𝕩` is `0`. Here is how we might make it behave like a control structure. {𝕤⋄a+↩10}⍟(a<10) @ The condition `a<10` is always evaluated, so there's no need to wrap it in a function. However, the function `{𝕤⋄a<10}` could be used in place of `(a<10)`, making the entire structure into a function that could be incorporated into other control structures. In the example shown, the value `10` appears in both the condition and the action, so it can be pulled out by using it as an argument. Depending on context this might be more or less clear. {a+↩𝕩}⍟(a⊸<) 10 For a more conventional presentation, the condition and action can be placed in a list, and `If` defined as a function. If ← {𝕏⍟𝕎@}´ If (a<10)‿{𝕤 a +↩ 10 } A final option is to use a [return](block.md#returns) 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. { 𝕊→⍟(¬a<10) @ # Return @ unless a<10 a +↩ 10 } 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 `@` in most examples above. ## Repeat 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. Another option is to use a [for-each](#for) statement with an argument of `↕n`: in this case the result is the list of each action's result. ## If-Else Despite the name, an if-else statement is most closely related to a [switch-case](#switch-case) statement: in fact, it's just a special case where the two cases are true (`1`) and false (`0`). As a result, we can implement it either with Choose (`◶`) or with [case headers](block.md#case-headers) of `1` and `0`. 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. IfElse ← {cond‿True‿False: cond◶False‿True @} IfElse ⟨𝕩