Another bite
We're only going to look at one more function from the Containers core protocol, flat-map
. I'll leave the others until I can introduce some more data types to illustrate their use.
The flat-map
protocol function is probably the single most useful of all the core protocol functions. What does it do? Glad you asked.
Suppose we wanted to see if the first element of a list of numbers was equal to 15. First, we need to get the first element of the list
(The =>
is just short hand for 'produces:'. Toccata doesn't have a REPL that you can type these expressions into yet. Look in the examples
directory for some short programs to run.)
So first
returns a Maybe value that has the first element in it. So far, the way we've seen to reach inside a Maybe value is with the map
function.
That's not right. What we need is a function similar to map
that will apply a given function to the value inside a Maybe value and then remove one layer of wrapping (or 'flatten') the result. flat-map
to the rescue.
But what happens when the list is empty and first
returns a nothing
value? Exactly what you'd expect.
And finally, what if the head of the list isn't 15?
And now, with lists!
How does flat-map
work with lists? Pretty straightforward. First regular map
.
Nothing too surprising, I hope. And now flat-map
And for completeness, flat-map
on an empty list
also, if the result of the given function is an empty list
for!
If you're a Clojure programmer, you might have thought about Clojure's for
expression for sequence comprehension.
Toccata has the exact same expression. It is another example of a special form that could be a macro. The above expression gets expanded to
So for
is written in terms of wrap
and flat-map
. But that also means that, in Toccata for
works for any data type that implements those function. Like Maybe
This is a huge thing in Toccata and we'll eventually spend a lot more time looking at this.