Zee Spencer

Using Nil Effectively

We seem to use nils in place of a default return value in a function. Say you wanted to write a function that splits a string on its commas:

def nil_split_on_comma(string)
  return nil unless string.include? ","
  string.split(",")
end

While this seems reasonable it can have some unfortunate side effects:

p nil_split_on_comma("asdfqwer").map(&:length)

Woops! Undefined method map for nil class! Let's try again!

def better_split_on_comma(string)
  return [] unless string.include? ","
  string.split(",")
end

p better_split_on_comma("asdfqwer").map(&:length)

Ah! Much better! Because this function always returns an object of the same type it can be used without checking the value! The astute reader will spot this as an example of the Null Object Pattern

In spite of it's lack of suitability as a replacement for a reasonable default value, I'm a fan of nil. I especially like it's use as a null terminator:

def iterable_fetch_val(index)
  data = "1234567890"
  data[index]
end

index = 0

while iterable_fetch_val(index)
  p iterable_fetch_val(index)
  index += 1
end

Here we're relying on the side effect that a nil value is also falsey. I'm less edgey about this because this functions use case is an iterator, instead of an accessor; but it's still a little iffy.

However, if you return an empty string instead of a falsey value it requires an additional method call to use as an iterator:

def uniterable_fetch_val(index)
  data = "1234567890"
  data[index] || ""
end

index = 0
until uniterable_fetch_val(index).empty?
  p uniterable_fetch_val(index)
  index += 1
end

As you can see, nil's aren't all bad. However they should be used with precision. Think about how varyied return types can cause complexity to move through the code.


Browse posts about:

Want to get notified when I publish new articles or update old ones? Subscribe to my newsletter. It's a weekly-ish set of interesting links with a short essay on programming, design, technical leadership, or anything else that strikes my fancy.

Not sure? Read the archive.