Let's write a generator that takes a
@ud (unsigned decimal) and returns a list
of its digits.
!: :- %say |= [* [n=@ud ~] ~] :- %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 |= [* [n=@ud ~] ~] :- %noun
The head of this cell is the literal
In the tail is the gate and its sample:
|= [* [n=@ud ~] ~]. 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
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
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
n is less than or equal to
0, we simply return
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
$ 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
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?