Flashback

I started programming in the early 80's. One of my first programs was something like

  10 PRINT "BUTTS"
  20 GOTO 10

Aside from being immature, it also used the primitive execution flow control GOTO. I expect most of you have heard tales of what code using goto's was like to write and debug. It was every bit as ugly and painful as you've heard. But even by that time, the so called "goto wars" were over and block-structured programming was ascendant. Which is not to say it was all sweetness and light. As painful as using goto's was, many argued vodiferously that they could not be removed. That they were an essential part of programming. The goto was an abstraction of the underlying hardware that leaked through and popped up in the higher level languages.

Today

Plugging that leak cut a tie to the lowest levels of abstraction that kept us from writing higher-level code and ultimately limited the size of the software we could write. Today, it's time to cut the last tie.

Booleans.

A boolean value only carries a single bit of information. This is an echo of the fact that fundementally, computers only operate on 1's and 0's. The associated language feature, the if statement is a blight on our ability to reason about our code and responsible for all the present ills in our industry. (hyperbolic sarcasm alert!)

But seriously, when I read about boolean blindness, the idea captured my imagination. What would a language without booleans look like? Would there be a benefit? Once I got over the (small) initial hump, I actually found it easier to program without booleans, if or cond. It's early days yet, so I'm very interested in other people's experience.

Maybe, or, and

We can't just eliminate booleans. They must be replaced with something. In Toccata that something is the Maybe data type. Maybe values may contain another value, or may be empty. The Maybe type also implements some of core protocol functions. One of those functions is extract which pulls the value from inside a Maybe value. Of course, if the Maybe value is empty, that's going to blow up.

But that's not quite enough. Toccata is strict, meaning that all values passed to a function are evaluated before the call. But we absolutely need a way to only evalute certain expressions depending on the results of comparisons, for example. The Toccata compiler provides two foundational special forms for this, and and or.

  (= x 15)

Will evaluate to the nothing value if x is not 15. But if x is 15, that expression evaluates to a Maybe value that contains a 15.

  <Maybe 15>

An or expression will evaluate each of the clauses one at a time until a clause does not evaluate to nothing. That value is what the or expression then evaluates to. Any remaining clauses are not evaluated.

  (or (= x 15)
      (maybe 21))

evaluates to <Maybe 15> if x is 15. Otherwise, it evaluates to <Maybe 21>.

The and expression evaluates each clause one at a time until one does evaluate to nothing, in which case the and expression evaluates to nothing as well.

But if none of the clauses evaluate to nothing, the value of the last clause is what the and expression evaluates to. So

  (and (= x 15)
       (= y 98))

evaluates to nothing if x does not equal 15 or y does not equal 98. But if both those clauses evaluate to <Maybe 15> and <Maybe 98> respectively, the and expression evaluates to <Maybe 98>.

With just these, I was pretty much able write the entire Toccata compiler in Toccata itself.

either

But there was one fly in the ointment. I had quite a few expressions that looked like

  (extract (or (= x 15)
               (maybe 21)))

Which is just ugly. I left those expressions in the code as an incentive to find a better way. And finally, last week, inspiration hit out of nowhere. (Literally. I was driving and thinking about something totally different.) I added a new special form, either.

  (either (= x 15)
          (inc x))

This expression evaluates to 15 if x is 15 and x + 1 in all other cases. But the call to inc will only be called if x is not 15. This new expression let me clean up a lot of ugliness and I'm expecting to clean up more when I have a chance.

And now I see

Obviously, or and and expressions can be nested to any depth. And the first clause of an either expression can be as complicated as needed.

I think this is sufficient to replace booleans and cut that final tie to the low level. But I'm open to coming up with solutions to other use cases that I haven't uncovered yet.