Why does NSArray arrayWithObjects require a terminating nil?

It all has to do with the C calling ABI.

Consider these methods:

- (id)initWithFormat:(NSString *)format, ...;
+ (id)arrayWithObjects:(id)firstObj, ...;
+ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;

The ... tells the compiler that a variable number of arguments of any type may be present. There is no way for the compiler to know what those types are required to be (the real definitions have markers that help with that).

Now, consider the three methods. All three have vastly different requirements for what might be present in the variable argument list. An array must be a bunch of objects followed by a nil. The dictionary requires a bunch of pairs of objects followed by a nil. Finally, the string method requires a bunch of arguments that match the types in the format string.

All of these behaviors are directly tied to the method being invoked and, if the author of an API decided to go for "hard to use", the behavior of decoding the variable arguments could be modified at runtime, just to make life difficult.

Bottom line: The C ABI doesn't have a syntax that allows for specifying that a method or function takes a variable number of arguments with any kind of set of constraints on the arguments or their termination.

Objective-C could change the rules just for method declarations & invocations, but that wouldn't help with C functions or C++, both of which Objective-C must remain compatible with.


Any varargs function requires someway to know how many parameters are present -- if you don't nil terminate, you would just need something else. In this case the obvious alternative is a length, but then you'd need to update the length argument everytime you changed how many items were in the array, and that could be cumbersome, or worse broken.

I am guessing you have an array that may contain nil?


@bbum gives some great technical details. Here are some thoughts on the practical "why don't they fix it?"

Remember: C is just assembler and Obj-C is just C... It could be redesigned of course, but there's almost no pressure to do so. You still couldn't put nil in an array (that would require a huge change). The compiler now warns you if you forget the nil, so it's not something developers complain a lot about. The trade-off is keeping the language much (much!) simpler than its kin, getting the benefits of decades of C-compiler optimizations and guaranteed compatibility with C code.

One thing that should become clear from @bbum's discussion: NSArray is not a language feature of Objective-C. C-arrays are a language feature, but NSArrays are just another object, no different than the objects you write.

Tags:

Objective C