Every tool is designed with a certain use in mind and using the tool in the way it was designed is often much easier. So starting with this post, I want describe how I intended Toccata to be used; The Toccata Way.
However, programming languages are incredibly malleable, so what I describe as The Toccata Way could very well change as people use it and discover better ways of doing things. Nothing I write here is cast in stone and I would love to be shown better ways of creating software using Toccata.
The programming triple
All programming boils down to telling the computer to do something in very small steps and there are 3 fundemental constructions used to build a whole program out of these small steps.
- Executing steps in sequence one after the other.
- Choosing one of a number of sequences of steps to execute.
- Executing a sequence of steps repeatedly with different inputs
Together, I consider these the "control-flow triple" and it appears everywhere I look at all levels of abstraction from assembly language to the highest level languages. Even declarative logic programming languages like miniKanren (or Prolog), have analogous constructions.
In Toccata, and most other languages, sequencing steps is so trivial that it's almost invisible
expr1 is done first followed by
expr3 and finally
expr1 which produces the final result.
I'll address repeatedly executing a sequense of steps in the next post. So now, let's look at choosing.
A Time for Choosing
Let's revisit the
"Folks" is a little generic, so let's personalize it a little by letting a name be passed in on the command line.
args parameter to the
main function is a list of strings that are the command line arguments to the program. The first string in the list is the name of program that was executed which we'll mostly ignore. So we need to get the second item from the list. The
second function from the core library does exactly that. Except it returns a Maybe value that we need to extract the actual name from. But there might not have been a name passed in on the command line. So we need to account for that.
I encourage you to run this for yourself.
Let's say we want to personalize it further by having a table of names mapped to a corresponding greeting.
So we need to get the second arg as above, and then use that name to get the salutation. But several things could go wrong. The name may not be in our map, or there may not be a name given on the command line at all. We'll use the
flat-map function, which is defined for Maybe values, to chain some calls to functions together sequentially. But if any of them return
nothing, the whole expression short-circuits and returns
In this case, the
map expressions both apply a function to a Maybe value. The anonymous
fns only get called if the Maybe values are not
nothing. Hopefully that construction is obvious given the explanation in the Containers post.
Let's clean this up a little. We can use a
for expression to refactor the
Having two calls to
second is a little ugly, so let's pull that out
I'm sure there are other ways to write this little ditty that improve on this.