Control Structures

As the name implies, control structures are used to control which parts of the program will execute. They are used to select between different branches in code or repeat some action multiple times. Often the choice of executing a specific branch is done based on some value or combination of several values. First we’ll have a look at some common predicates [1] and how to combine them. After covering them, we’ll dive into various control structures and their applications.

Boolean algebra

Boolean algebra [2] is very basis of how computers operate. It consists of two values True and False and set of basic operations and, or, not and xor.

Hy adds a little twist in the Boolean algebra. Instead of operating strictly only on True and False values, it can operate on almost any value. Values that evaluate to True in Boolean algebra are considered to be truthy values. Conversely, values that evaluate to False in Boolean algebra are considered to be falsey values. Following list shows values considered falsey, all other values are considered truthy:

  • None
  • number 0
  • any empty sequence or collection

And operator takes 0 or more arguments and returns last argument if all of them are True or no parameters were passed at all, as shown below. Notice how in the last example we’re passing in three numbers and last one of them is returned as the result. This is because all of them are truthy, so the final one will be returned. Sometimes this technique can be useful, for example when you want to first check that set of variables are truthy and then perform an operation with the last one of them.

=> (and True True)
True
=> (and True False)
False
=> (and False False)
False
=> (and)
True
=> (and 1 2 3)
3

Or operator takes 0 or more arguments and returns first truthy argument if one or more of them are True. Some examples of usage are shown below. Notice how or without any arguments doesn’t seem to return anything. This is because in that case it returns None, a special value denoting non-existant value (which is also considered falsey) and REPL doesn’t print it on screen.

=> (or True True)
True
=> (or True False)
False
=> (or False False)
False
=> (or)
=> (or 1 2 3)
1

In order to see actual return type, one can use type as shown here:

=> (type (or))
<class 'NoneType'>

Sometimes there’s need to reverse Boolean value, so that True turns to False and False turns to True. That can be achieved with not operator. It takes one argument and always return either True or False, as shown below. While it’s possible to call not with truthy values, it will not be able to deduce corresponding opposite value, which is the reason why only True or False is returned.

=> (not True)
False
=> (not False)
True
=> (not 1)
False
=> (not [])
True

The final operator we’re going to learn now is xor, short for exclusive or.

fill in xor here

Short circuiting

fill in details here

Common predicates

<, >, <=, >=, =, !=, integer?, odd?, even?

Branching

do

if, if*, if-not, when, cond, lif, lif-not, while, unless

every?

Looping

for, break, continue

while

reference to recursion

[1]predicate is a test that evaluates to True or False
[2]Boolean algebra, also known as Boolean logic, is named after its inventor George Boole