On a different note…
1. On Procedures and Functions
In FORTRAN and Pascal and Ada, programming languages that I revelled in long ago, there is a distinction drawn between so-called procedures on the one hand and functions on the other. Both are software constructs for doing some work, but whereas a function calculates a tangible result and gives it back to the caller, a procedure does no such thing, performing instead some background operation on behalf of the caller (for instance printing some text to the screen or saving some data in a database).
So in Ada you might write
function Translate( english_word : String ) return String is begin ...translation algorithm here... return swahili_word; end
and
procedure Display( sentence : String ) is begin ...output algorithm here... end
In a sense, functions produce stuff that you can take with you whereas procedures just do stuff.
2. Unifying Them Both
In contrast to this, the languages C, C++, C# and Java have no such distinction. They only have functions.
Well, that’s not quite right, because of course there’s still a need for algorithms that do stuff. And so in place of procedures, these languages define so-called void functions. They produce nothing whence void.
In a hypothetical language might this could take the following form.
function Display( sentence : String ) return void is begin ...output algorithm here... end
To an engineer encountering this stuff for the first time, this notion of void functions is entertaining. It’s novel to reflect on the notion that the void has entered into an otherwise dry world of physics and equations of motion and all that.
But it’s not a confusing concept, so after a few minutes the novelty fades, and you proceed as you always have, writing some functions that produce something and other procedures functions that don’t.
3. void
Isn’t a Type
Now, the languages mentioned above are examples of so-called statically typed languages. That is to say, every algorithm expressed in these languages manipulates things that have a so-called type (String, Integer, Character, …), and these types are explicitly specified by the programmer. So you might wonder, What is this type called void
?
Well, I am not a programming expert, but my understanding is that in fact in these cases, void
isn’t really a type per se. It’s just a hint to the computer that this particular function actually doesn’t return anything.
Hm… It’s a hint that this function isn’t producing anything; that it’s only doing something. In other words, void
is just an annotation that says, Hah! Fooled you. This isn’t really a function at all; it’s a procedure.
4. Introducing Unit
This state of affairs changes a bit in the Scala programming language, a language built on the conceptual foundations of C and Java but one that goes in some fundamentally different directions.
Scala generalizes the notion of void
to a full-fledged type called Unit
. So in Scala you might write something like this.
def Display( sentence : String ) : Unit = { ...output algorithm here... }
Or using the Ada-like pseudocode we’ve used above,
function Display( sentence : String ) return Unit is begin ...output algorithm here... end
The only real difference here is the presence of Unit
instead of void
. But in Scala, this is no minor detail. Whereas the void
of C is a kind of hint, Scala’s Unit
is a bonafide type.
5. A Tangent on the Notion of Unit
Unit
made me do a double-take when I first saw it. After all, using Unit
to represent “nothing” sounds perilously close to the heresy of claiming that 1=0
. It turns out that I’ve run into this heresy before.
Once upon a time I was working with a bunch of rocket scientists. We were building a new space transportation system that was going to take us to orbit, take us to the moon and eventually take us to Mars. One of the projects I was working on involved designing a schema for representing complex datasets in a way that future engineers and software developers could understand long after the original authors were gone. (This system was being designed for the long-haul, an irony given that the project was eventually cancelled.)
I worked with a couple computer science-y, math-y guys from California. They were bright, and they were determined to apply their dreams of ontologies to the problem I was working on. One day we were discussing how to specify … nothing — how to formally indicate that there was nothing there there.
“Can we call this Unit?” Oliver asked.
I was puzzled. Why would we call nothing one?
See the connection, here?
6. Another Tangent
I’m not a computer scientist. Indeed, in an interview question long ago, I was asked some computer science-y, algorithm-theoretical question to which said, “I confess I’m not strong in …” to which the questioner responded, “Aren’t all computer scientists strong in …?” to which I reminded him that my background was in engineering.
Neither am I a mathematician. But let me point out something about Monoids. In abstract algebra, a monoid is a pair (S
,op
) where S
is some set and op
is a binary operation (function) on that set that returns elements of the set. There are some axioms surrounding S
and op
, namely the axioms of closure, associativity and identity.
It’s the notion of identity that is relevant, here. The identity axiom simply stipulates that there is some element in the set S
, let’s call it I
, for which (I op x) = x
for all elements x
in S
.
Hmm… This is a bit abstract. But wait, don’t leave.
Let’s consider the case where op
is the binary operation of adding two numbers together. In this case, I
is 0
(zero), since any number plus zero gives you the original number.
Now let’s consider the case where op
is the binary operation of multiplying two numbers together. Here, I
is 1
(one), since any number times one gives you the original number.
And are you seeing my point, here? When those ontology guys asked me if it was ok to use the term “unit” to refer to “nothing,” it must have had something to do with monoids. Unit
must be related to some theoretical notion of identity, and in the context of multiplication, the notion of identity is indeed… one. Hence the term unit?
Anyway, let’s return to Scala’s type system…
7. Unit
and Nothing
So Scala has this thing called Unit
. It’s a type in the language used in situations where a function actually returns nothing.
In some sense Unit
means nothing. Personally, I would have chosen Nothing
rather than Unit
as way to say …you know… “nothing”. But it turns out that the type Nothing
is used in Scala for something else.
Nothing
is one of the so-called bottom types in the language. It is a subtype of every other type in the language. And rather than denoting “nothing” as the term suggests, Nothing
actually denotes “never”. When a function is intentionally designed never to return you specify its return type as Nothing
. Personally, I would have chosen …you know… Never
to capture this. But remember, I am not a computer scientist.
Using the same pseudocode as above, you might write such a function as follows.
function Event_Loop() returns Nothing is begin while(true) begin ...event processing here... end end
You can see from that never-terminating loop that the function never returns, it just loops around again and again, processing events ad infinitum. (You have to admit, return Never
would have fit this situation really well.)
Admittedly, all this one is nothing and nothing is never is… well, confusing. But frankly, once you get passed this minor hurdle, the details of the Scala type system are frankly stunning.
But that, dear reader, is a topic for another day.