Let's write a generator that takes a
@ud (unsigned decimal) and returns a list of its digits.
!: :- %say |= [* [[email protected] ~] ~] :- %noun =| lis=(list @ud) |- ^+ lis ?: (lte n 0) lis %= $ n (div n 10) lis (mod n 10)^lis ==
We're creating a
%say generator. That means we need some “boilerplate” code in the format of
[%say [%noun "data"]]:
:- %say |= [* [[email protected] ~] ~] :- %noun
The head of this cell is the literal
In the tail is the gate and its sample:
|= [* [[email protected] ~] ~]. This is where we describe any arguments we are expecting to be passed in when the generator is called. We are expecting data of type
@ud. We give the data the face
n so that we can easily reference it later.
Also in the tail is another
cell, its head indicating to the
dojo how to print the value we are creating. In this case, we use the generic
The tail of our second cell is the product of the rest of the program.
=| lis=(list @ud)
We use the above code to construct a
@ud by cutting up the
@ud we got passed and so we add a face onto that type. This list is empty until we manipulate it further.
|- ^+ lis ?: (lte n 0) lis
|- creates a gate that functions as a recursion point.
We are actually able to reuse
lis for the type of output that we are going to produce. A sibling of the
^+ is distinct because it is for casting by example. It takes type information from an instance of that type. It's useful when using a complicated type.
?: (lte n 0) lis
?: checks if the statement that follows is true or false. In our case, if it's true that
n is less than or equal to
0, we simply return
lis. Otherwise, we branch to the following operations:
%= $ n (div n 10) lis (mod n 10)^lis ==
%= is the rune that takes a wing with any number changes, in the form of a list. Our list has two elements that represent such changes, contained in a
$ expression to perform recursion. This is the tall form of an equivalent syntax that you may be more familiar with:
$(n (div n 10), lis (mod n 10)^lis).
The first change divides
10, rounding down without a remainder, and assigning that product as the new value for
The second change prepends the remainder of
x^y is an alternative syntax for
mod performs the modulo operation.
Together, these operations will pull each digit out of
n and put it into a
list. That's because dividing
n by 10 will knock off one decimal place from the value, and
mod will store the actual discarded digit. To visualize this complementarity, let's run some operations in the dojo:
> (div 146 10) 14 > (mod 146 10) 6
* TODO What if we do this with vases? Can we accept a vase, map it to whatever the correct value would be to extract each digit of the number in whatever base we are interpreting it in?
* TODO from Rob: we need a few exercises here. Maybe asking the reader to make one that accepts a vase could be one?