1.3.1 Walkthrough: Conditionals
In this lesson, we will write a generator that takes an integer and checks if it is an even number between 1 and 100. This will help demonstrate how boolean (true or false) conditional expressions work in Hoon.
:- %say |= [* [n=@ud ~] ~] :- %noun ^- ? ?& (gte n 1) (lte n 100) =(0 (mod n 2)) ==
On the very first line, with
:- %say we are beginning to create a generator of the
%say variety. The result of a
%say generator is a cell with a head of
%say and tail that is a gate, itself producing a
cask, a pair of a
mark and some data. It's not important for understanding conditionals; this is just template code. For more information about
%say generators, see the Generators documentation.
|= [* [n=@ud ~] ~]
The code above builds a gate. The gate's first argument is a cell provided by Dojo that contains some system information we're not going to use, so we use
* to indicate "any noun." The next cell is our arguments provided to the generator upon invocation at the
dojo. Here we only want one
@ud with the face
This code is the third line of the
%say "boilerplate," and it produces a
cask with the head of
%noun. We could use any
mark here, but
%noun is the most generic type, able to fit any data.
This line casts the output as a
flag, which is a type whose values are
%.n representing "yes" and "no". These behave as boolean values.
Let's look at the conditional.
?& (gte n 1)
?& (pronounced "wut-pam") takes in a list of Hoon expressions, terminated by
==, that evaluate to a
flag and returns the logical "AND" of these
flags. Most runes take a fixed number of children, but the handful that do not (such as
?&) end their list of children with a terminating rune. In our context, that means that if the product of each of the children of
%.y, then the product of the entire
?& expression is
%.y as well. Otherwise, the product of the conditional
The first child of
(gte n 1). It is good practice to put the first boolean test of a conditional on the same line as the conditional as we have done here. This utilizes the standard library function
gte which stands for "greater than or equal to".
(gte a b) returns
a is greater than or equal to
Next we have:
(lte n 100)
lte is the standard library function for "less than or equal to".
(lte a b) returns
a is less than
The last boolean test we have is
=(0 (mod n 2))
This checks to see if
0 is equal to
(mod n 2) - in other words, checking if
n is even. It produces
n is even and
n is odd.
It is good practice in Hoon to put "lighter" lines at the top and "heavier" lines at the bottom, which is why we have put
=(0 (mod n 2)) last in the list of conditionals.
Finally we have a terminator.
This marks the end of the list of children of
We only utilized one "wut" rune in our walkthrough, but there are many others. Here are a few more examples:
?:(pronounced "wut-col") is the simplest "wut" rune. It takes three children, also called sub-expressions. The first child is a boolean test, so it looks for a
%.n. The second child is a yes-branch, which is what we arrive at if the aforementioned boolean test evaluates to
%.y. The third child is a no-branch, which we arrive at if the boolean test evaluates to
%.n. These branches can contain any sort of Hoon expression, including further conditional expressions. Instead of the
?&expression in our
%saygenerator above, we could have written
?: ?& (gte n 1) (lte n 100) =(0 (mod n 2)) == %.y %.n
Of course, doing so would be needlessly obfuscating - we mention this only to illustrate that these two Hoon expressions have the same product.
?!("wut-zap") is the logical "NOT" operator, which inverts the truth value of its single child. Instead of
(lte n 100)in our
%saygenerator above, we could have written
?! (gth n 100). Again, this would be bad practice, we only present this as an example.
?@takes three children. It branches on whether its first child is an atom.
?^takes three children. It branches on whether its first child is a cell.
?~takes three children. It branches on whether its first child is null.
?|takes an indefinite number of children. It's the logical "or" operator. It checks if at least one of its children is true.
To see an exhaustive list of "wut" runes, check out the reference documentation on conditionals.