Hacker News new | past | comments | ask | show | jobs | submit login

As you can clearly see from the code it's perfectly acceptable in Objective-C to send a message to nil. This is a powerful feature that prevents the program from crashing but it is confusing for beginners.



It doesn't seem particularly confusing. It's pretty much the first thing you learn: square brackets send a message, and if there's no recipient, the return value will be zero. (Granted, it used to be more complicated in the PowerPC era, when e.g. a selector that returns a double was not guaranteed to return 0.0 with a nil receiver, but those cases were fixed in the runtime.)

I suspect the messaging-to-nil behavior is mostly confusing to intermediate programmers who only have experience with Java's passive-aggressive null references.


In my opinion the confusing part is not about SEGFAULT or NullPointerException. Let's make and example:

   NSArray *obj = nil;
   [obj count]; // return 0
In theory a nil object can hide in your code for a long time if you only use methods that can return 0.


There is no "natural" behavior to a beginner. Either way has to be learned and understood. Nil messaging behavior is only going to be confusing to people who learned one way and internalized it enough to think of it as "the way", then were exposed to the other way. Java programmers going to ObjC will find ObjC's nil handling confusing, and ObjC programmers going to Java will find Java's null handling confusing.


It's a trade-off, because it's convenient to not have to check that objects are non-nil when you send messages to them. With experience, you learn to deal with code that requires non-nil objects via assertions:

    NSAssert(array, @"Array can't be nil.");


Well, you have to learn what the "zero value" for each and every type is in order to fully understand the language semantics. IMHO, this adds complexity beyond null pointer exceptions.


You also need to understand "zero values" to understand what a freshly created object looks like (all of its instance variables are initialized to zero). So I don't think it would make Objective-C any easier to learn if messaging to nil would throw an exception.

Personally I find that the nil behavior provides a useful base guideline for API design. When defining a method signature in Obj-C, you have to ask yourself if it's clear to the user of the method what happens when the method (inevitably) gets sent to nil. In that way, you have to think about the circumstances of the API's actual use, rather than just the ideal case.


Pavlov, I think you meant square brackets


Yes, thanks! (I still haven't learned the English names for the various brackets, it seems... In my mind, the ones with the straight angles are the "angle" ones.)


() parenthesis

[] brackets

{} braces


For those learning English: parenthesis is the singular, parentheses the plural:

  (  opening parenthesis
  )  closing parenthesis
  () parentheses
  (( two opening parentheses
  )) two closing parentheses
Way more info at http://en.wikipedia.org/wiki/Bracket


And for those learning etymology, parenthesis comes from ancient Greek:

Parenthesis, from "para" (next, beside, near) and "enthesis" (embedd, inline). So, essentialy to "inline near/next to something" (what we do with a parenthetical phrase).


"Brackets" means () in standard usage (at least where I'm from); you need to say "square brackets" if you want to clearly mean [].


So is there are single-word name for "angle brackets", the ones you write with less-than/greater-than symbols?

If I had my way, I'd call them pointyparens.


The Hacker's Dictionary (http://www.dourish.com/goodies/jargon.html) calls them Brokets, as shorthand for "broken brackets".

And, by the way, the less pointy variant that is used in 'proper' typography is called a chevron or guillemet (http://en.wikipedia.org/wiki/Guillemet)


The ability to send messages to nil is not only there to prevent crashes. It can also be used to make clean APIs or to use APIs with a lot of convenience. It also gives you a lot of flexibility... It allows you to do the error handling on a case by case basis. If you are not interested in erros simply do not check for nil and go on...

    Object *o = [Object new];
    if(o==nil) { /*handle error and return */ return; }
    [o doSomething];
vs.

    Object *o = [Object new];
    [o doSomething];
In the first case I catch a potential error explicitly and in the second case I simply send doSomething to nil which is perfectly fine.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: