In objective-c, nil is expected to sort of propagate as opposed to causing an immediate failure. Sending a message to nil (essentially) always results in nil. Is there a similar expectation when sending a nil argument, when that makes no sense?
The particular case I have in mind is essentially the functional map
method:
-(NSArray*) map:(id (^)(id item))projection {
if (projection == nil) {
// ?? what to do ??
// throw exception?
// return nil?
// return empty array?
}
NSMutableArray* r = [NSMutableArray arrayWithCapacity:[self count]];
for (id e in self) {
[r addObject:projection(e)];
}
return r;
}
Should passing a nil block for projection cause some sort of failure, or some sort of default result?
My personal preference is to fail-fast, but I see objective-C favoring fail-do-nothing in many places. I would appreciate input on what the expected convention is in this sort of case.
edit
More specifically, is it acceptable to do this:
#define require(expr) \
if (!(expr)) \
@throw([NSException exceptionWithName:NSInvalidArgumentException \
reason:[NSString stringWithFormat:@"!require(%@)", (@#expr)] \
userInfo:nil])
-(NSArray*) map:(id (^)(id item))projection {
require(projection != nil);
...
Generally speaking, if your method requires that a parameter is not nil, you'd better bail out as soon as possible in case it is.
With this in mind
NSParameterAssert(item)
is a good practice. It is thoroughly explained here, but the quick summary is that it throws an NSInternalInconsistencyException
in case the assertion is not satisfied.
Note that by default the NSParameterAssert
macro (as well as all the others NSAssert
-like macros) is removed in release builds, unless you undefine NS_BLOCK_ASSERTIONS
.
More on the subject is explained here.