on master help sign in
Merge pull request #728 from urbit/conditionals

Conditionals

commitf7d1530a26172d333cdd648b8209c032a36ecc7f authorDavid Kerschner <david@tlon.io> dateTue 26 Nov 2019, 11:32 (7 years ago) parent7db69b0b837b45
1 file changed+43−20
tutorials/hoon/conditionals.md+43−20
tutorials/hoon/conditionals.md+43−20
@@ -11,13 +11,11 @@ In this lesson, we will write a generator that takes an integer and checks if it
1111:- %say
1212|= [* [n=@ud ~] ~]
1313:- %noun
14−?: ?& =(0 (mod n 2))
15− ?& (gte n 1)
16− ?! (gth n 100)
17− ==
18− ==
19− %.y
20−%.n
14+^- ?
15+?& (gte n 1)
16+ (lte n 100)
17+ =(0 (mod n 2))
18+==
2119```
2220
2321On 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](@/docs/tutorials/hoon/generators.md) documentation.
@@ -34,33 +32,58 @@ The code above builds a gate. The gate's first argument is a cell provided by Do
3432
3533This 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.
3634
37−But now let's get into the conditionals themselves. Below we'll examine the series of `?` runes used.
38−
3935```hoon
40−?: ?& =(0 (mod n 2))
36+^- ?
4137```
38+This line casts the output as a `flag`, which is a type whose values are `%.y` and `%.n` representing "yes" and "no". These behave as boolean values.
39+
40+Let's look at the conditional.
4241
43−`?:` (pronounced "wut-col") is the simplest "wut" rune. It takes three children, also called sub-expressions. The first child is a boolean test, which means that it looks for a `%.y` ("yes") or a `%.n` ("no."). 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, so we arrive at it if instead the boolean test evaluates to `%.n`. These branches can contain any sort of Hoon expression, including further conditional expressions, as we will see.
42+```hoon
43+?& (gte n 1)
44+```
4445
45−In our case, the first child of `?:` is `?& =(0 (mod n 2))`. It itself has another conditional rune, `?&` ("wut-pam"), which performs the logical "and" operation on its two children, making sure that both of them are true. The first child of our `?&` rune is `=(0 (mod n 2))`, which simply asks if `n` is even or not.
46+`?&` (pronounced "wut-pam") takes in a list of Hoon expressions, terminated by `==`, that evaluate to a `flag` and returns the logical "AND" of these `flag`s. 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 `?&` is `%.y`, then the product of the entire `?&` expression is `%.y` as well. Otherwise, the product of the conditional `?&` is `%.n`.
4647
47−The second child is:
48+The first child of `?&` is `(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 `%.y` if `a` is greater than or equal to `b`, and `%.n` otherwise.
4849
50+Next we have:
4951```hoon
50− ?& (gte n 1)
51− ?! (gth n 100)
52− ==
52+ (lte n 100)
5353```
54+`lte` is the standard library function for "less than or equal to". `(lte a b)` returns `%.y` if `a` is less than `b`, and `%.n` otherwise.
5455
55−Its first child is another `?&` rune. This second "and" rune checks for the truth of the following two expressions: `(gte n 1)`, meaning "n is greater than or equal to one"; and `?! (gth n 100),` which means "n is not greater than 100".
56+The last boolean test we have is
57+```hoon
58+ =(0 (mod n 2))
59+```
60+This checks to see if `0` is equal to `(mod n 2)` - in other words, checking if `n` is even. It produces `%.y` if `n` is even and `%.n` if `n` is odd.
5661
57−`?!` ("wut-zup") is the logical "not" operator, which inverts the truth value of its single child. We would normally use simpler code here to do the same thing: `(lte n 100)`, without the `?!` rune. We're just using this rune artificially to demonstrate its use to the reader. The `==` runes close the `?&` runes, since `?&` runes can take an unlimited number of children.
62+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.
5863
59−So the two `?&` runes that we used in this code together check the that all three of these different expressions evaluate to true: `=(0 (mod n 2))`, `(gte n 1)`, and `?! (gth n 100)`. If all of these expressions evaluate to true, our original `?:` expression branches to the `%.y` we wrote on the second-to-last line; if one or more evaluates to false, it branches to the `%.n` on the final line. Try to visualize how this works by looking through the program and examining the indentation.
64+Finally we have a terminator.
65+```hoon
66+==
67+```
68+This marks the end of the list of children of `?&`.
6069
6170### Other Runes
6271
63−We only went into three "wut" runes in our walkthrough, but there are many others. Here are a few more examples:
72+We only utilized one "wut" rune in our walkthrough, but there are many others. Here are a few more examples:
73+
74+- `?:` (pronounced "wut-pam") 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 `%.y` or 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 `%say` generator above, we could have written
75+
76+```hoon
77+?: ?& (gte n 1)
78+ (lte n 100)
79+ =(0 (mod n 2))
80+ ==
81+ %.y
82+%.n
83+```
84+Of course, doing so would be needlessly obfuscating - we mention this only to illustrate that these two Hoon expressions have the same product.
85+
86+- `?!` ("wut-zup") is the logical "NOT" operator, which inverts the truth value of its single child. Instead of `(lte n 100)` in our `%say` generator above, we could have written `?! (gth n 100)`. Again, this would be bad practice, we only present this as an example.
6487
6588- `?@` takes three children. It branches on whether its first child is an atom.
6689