5 ms·
> In other languages, like C++, this would crash your program, but in Objective-C, invoking a method on nil returns a zero value. This greatly simplifies expres
by SeanLuke 14y ago
> In other languages, like C++, this would crash your program, but in Objective-C, invoking a method on nil returns a zero value. This greatly simplifies expressions, as it obviates the need to check for nil before doing anything:
// For example, this expression...
if (name != nil && [name isEqualToString:@"Steve"]) { ... }
// ...can be simplified to:
if ([name isEqualToString:@"steve"]) { ... }
Wow, that is some bad, bad code. Consider this snippet instead:
if ([name isDifferentFromString:@"bob"]) { ... }
- tyler-dodge 14y agoThat seems like a naming decision, I think it'd make more sense to have an equals selector than a not equals selector in objective c. Plus isEqualToString: is already part of NSString
- efnx 14y agoThat's not bad code, you must be sarcastic. I've never heard of the method isDifferentFromString: and besides, the method name suggests it's the same thing as isEqualToString: approached from the other side. Are you referring to the capitalization mistake in @"steve"? When using sarcasm keep in mind there's no tone in text ;)
- optymizer 14y ago<sarcasm>Well, if you've never heard of it then it cannot exist and that invalidates his example, right? </sarcasm> I'm not saying the example is correct, I'm pointing out that "I've never heard of it" / "Works on my computer" are dangerous attitudes to have.
- efnx 14y agoI'm sorry, I should have been more clear. I meant "I've never heard of that method, so I looked it up in Xcode and it turns out it is not a method on NSString (and why should it be if !isEqualToString: achieves the same purpose?) which leads me to believe that this comment is sarcasm, if it isn't can you please clarify?"
- alayne 14y agoHe's not being sarcastic. Maybe a better example of what he is trying to get at is if (![missleLauncher isDisabled]) { /* declare thermonuclear war */ } When missleLauncher is nil, thermonuclear war is still declared which may not be the programmer's intent.
- xsmasher 14y agoProperties and methods are given "positive" names as a matter of convention, and to make reasoning about Nil easier. In Objective-C, the question "should I name my method isEnabled or isDisabled?" has a reasonable answer - you consider what makes most sense (or any sense) when called on Nil. This is probably a good rule for other languages too - "negative" booleans can lead to double-negatives and unreadable code.
- alayne 14y agoEven with a positive naming convention, you will have conditionals for the negative case, e.g. if (![str isEqualToString:@"myvalue"]) and falling into its block is not desirable when str is nil. Personally I have had plenty of bugs around things being unexpectedly nil, but I can't think of a case like this where I executed a block unexpectedly.
- ajanuary 14y agoYou do raise an interesting point that a nil swallowing language forces you to write your methods in such a way as to logically return false for a nil receiver. I'd argue this is the way most methods are naturally written, so it doesn't have too much of an impact. I'm struggling to think of an example where logically returning true for a nil receiver is a much more natural than the other way around. Most of them, including your example of isEqualToString vs. isDifferenceFromString, are at best equal. It's probably something that should be made more explicit in discussions about nil swallowing, such as the OP.
- judofyr 14y ago`[a compare:b]` returns 0 both if they are equal and if a is nil.
- tyler-dodge 14y agoTrue, although none of the other return values make that much sense with nil either.
- ajanuary 14y agoCheers for the counter-example. I can't think of a compare method in the Objective-C core lib (the biggest nil-swallowing lib I know of). Does anyone know of one? Would be interesting to see how it's handled and if it causes issues. You could return an enum, which would allow you to use non-obvious values (Lower = 1, Equal = 2, Higher = 3), though this would make it a bit of a pain to interface with C-style libs. Obviously the presence of a work-around doesn't mean nil-swallowing is a good idea, but rather cements the idea that library authors need to put in extra effort to make sure nil receivers are handled appropriately.
- judofyr 14y ago> I can't think of a compare method in the Objective-C core lib (the biggest nil-swallowing lib I know of). Does anyone know of one? Would be interesting to see how it's handled and if it causes issues. Maybe I misunderstood you, but there is plenty of compare:'s in Cocoa: http://cl.ly/image/1a112f1B1W1g http://cl.ly/image/1a112f1B1W1g. They all return an enum that's either -1, 0 or 1.
- kstenerud 14y agoWhy is it bad code? If name is nil, isEqualToString will return false. And that's correct behavior because nil is not equal to the string @"steve".
- nicholassmith 14y agoNo snark: could you explain why it's bad code for you?
- mpweiher 14y agoYou generally try to make tests positive, which then makes this work ( -isEqual: rather than -isDifferent:). Of course, there is one place where you have to go the other way: -isNil: does not work, you need to use -isNotNil Unless you use the runtime's (private) nil-hook: +(void)setNilHandler { installed=YES; _objc_setNilReceiver([self nsNil]); } Then you can send messages to nil and they will be sent to your class. Of course, you want to mimic the nil-eating behavior as much as possible, so: static id idresult( id receiver, SEL selector, ... ) { return nil; } +(BOOL)resolveInstanceMethod:(SEL)selector { class_addMethod(self, selector, (IMP)idresult , "@@:@"); return YES; }