Skip to content

Unit and Nothingness

Sat, 23 Nov 2013, 03:15 PM (-06:00) Creative Commons License

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.

© jumpingfish by David Hasan is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License