nil vs None

Recently I saw a question like:

Isn’t nil the same as None?

This is my attempt to answer this question.1 And no, they are not the same thing.

Let’s consider the following function using a hypothetical language syntax:

def sum(a: Int, b: Int) -> Int
  a + b
end

There’s nothing preventing someone to do this:

def sum(a: Int, b: Int) -> Int
  nil
end

Which you could think being the same as:

def sum(a: Int, b: Int) -> nil
  nil
end

One way to interpret this is to consider that nil is a subtype of Int and that’s why no error is thrown at compile time. One example of a bad type system that allow this is Java’s where you can return null from a method that its return type is Integer. If it were int it wouldn’t be possible since int is a primitive type.

Now let’s see the case of using Option<T>2:

def sum(a: Int, b: Int) -> Option<Int>
  Some(a + b)
end

Of course you can return None from it:

def sum(a: Int, b: Int) -> Option<Int>
  None
end

Can we replace the return type to None the same way we did with nil?

def sum(a: Int, b: Int) -> None
  None
end

That’s not possible since None is not a type, it is actually a value of type Option<T>.

Notice the difference? Instead of having a type that represents the absence of a value, there’s just a type that represents an optional value.

Notes

  1. Please bear in mind that I am not a PLT expert. 

  2. Option<T> can be defined as:

    enum Option<T> {
      Some(T),
      None,
    }