Question

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);
    ...
Was it helpful?

Solution

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.

OTHER TIPS

Since projection is a block, not an object, you cannot just ignore checking for it to be nil; you must do the check and react as you need. It's up to you if that reaction means throwing an exception, returning nil, or something else.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top