nil

Objective-C has a neat little thing called nil, which represents the absence of an object. It’s like null in Java or JavaScript, or NULL in C, but with one important difference: you can call methods on it.

“Bwah?” you say, wondering why that would be a feature rather than a bug. Yes, that was my first reaction too. But after much use, I have decided that it is indeed a feature.

Send a message (i.e. call a method) — any message — to nil, and the response is always 0, i.e. nil. It’s counter-intuitive that nil is a good thing, because it seems like it would be a good way to mask errors.

And it can mask errors, but not usually. More importantly, effective use of nil cleans up tons of code that would otherwise be filled with if (foo == nil) checks.

Consider: object X holds a delegate “foo” which is notified about various events that happen to X. This delegate foo is connected to X by code external to both X and foo.

Now, this foo thingy isn’t really essential to the proper functioning of X. X doesn’t care about foo, foo cares about X. So why in the world should X be responsible for figuring out whether foo has been set or not?

Enter nil. X doesn’t need to know whether it’s delegate foo has been set or not, it just sends messages. If there’s no foo there, the messages disappear into the ether. Meanwhile X’s code is easier to read, because it doesn’t jump through hoops to guarantee that foo present.

I like nil. A lot.

(Update: some commenters have expressed concern about the effect of nil within arithmetic operations. It’s an understandable concern, but not relevant to Objective-C. Nil is an object type, not a primitive type. And as those of you familiar with C and Objective-C already know, primitive types don’t coerce to objects, and there’s no operator overloading. So nil doesn’t ever participate in arithmetic operations.)

6 thoughts on “nil

  1. As I don’t know Objective-C, I’ll phrase this answer as if nil were a feature of C#, and for convenience, as if int x = nil; was valid.

    int celsius;
    try
    {
    . . celsius = GetIntFromUser();
    }
    catch (UserDidntProvideAnInt doh)
    {
    . . celsius = nil;
    }

    WarmUpBy(25-celsius);

    So if the room is 20 degrees and the user doesn’t provide an int, we warm the room up by 25 degrees instead of 5. Oh dear.

    Now let’s imagine that C# has Maybe int. Oh, it does, it’s called “int?”.

    int? celsius;
    try
    {
    . . celsius = GetIntFromUser();
    }
    catch (UserDidntProvideAnInt doh)
    {
    . . celsius = null;
    }

    celsius.IfNotNull(c => WarmUpBy(25-c));

    IfNotNull is not a member of Nullable but it’s easy to add as an extension method. Similar techniques can make Nullable useful, though Nullable is restricted to value types, so you will find Maybe in Mono.Rocks, which is unrestricted. This is by no means limited to C#, but C# is the most mainstream language in which this is readable, as far as I can tell.

  2. Neil says:

    @ricky: nil is an object type, it’s not used for primitive data types.

  3. StormSilver says:

    I think that Objective-C is like this a lot. You start out and you’re like “WHOA WTF SQUARE BRACKETS”. Then you use it for a while and you start to like them. And you keep running into weird things, design decisions that just seem strange. But you get to know it and you start to like it. Then you switch back to, say, Javascript, which is a great language, but it seems… lacking. It is probable that I have an Apple bias here, but I must agree. I like nil. A lot.

  4. Pete Kirkham says:

    >WarmUpBy(25-celsius);
    >
    >So if the room is 20 degrees and the user doesn’t provide an int, we warm the room up by 25 degrees instead of 5. Oh dear.
    if nil is an object and infix operators are implemented by sending messages, then assuming 25.operator-(nil) gives the same result as nil.negate().add(25) => nil, so you warm the room up by nil, not 25. So the issue would be with nil, but that nil can be silently coerced to int(0).

  5. Marco DiPlacido says:

    this is very cool as indeed, in my experience with C# if you have a delagate which you would like to call you must first check if it is null before making the call

    C# eg.

    if (myDelegate != null)
    {
    myDelegate(arg1Value, arg2Value);
    }

    in objective C this compresses to

    [myDelegate param1: arg1Value param2: arg2Value];

    that’s it! no need to check if myDelegate has been set in objective C. in C# you will get an exception if you do not do the check.

  6. Andrey says:

    The Maybe monad accomplishes a similar thing in Haskell (although it’s been implemented in other languages, also). Oliver Steele explains it better than I can:

    http://osteele.com/archives/2007/12/cheap-monads