A similar but arguably more useful version of this is when you have two variables, one of which may be null. Traditionally you issue an if-condition test using the variable user input as the left operand but switching it handles the null case automatically.
Ex:
Foo SOME_CONSTANT = <something-not-null>;
Foo userSuppliedInput = <some-user-input-possibly-null>;
// This can raise an null pointer exception
if (userSuppliedInput.isEquals(SOME_CONSTANT) {
// ...
}
// This can't raise a null pointer exception (assuming isEquals handles nulls properly):
if (SOME_CONSTANT.isEquals(userSuppliedInput) {
// ...
}
Objective-C is really fun here. Messages to nil are no-ops which return zero, which for booleans results in false. Thus, the conditional works just fine either way:
If userSuppliedInput is nil, the isEqual: returns false, and it works.
It gets really fun when both might be nil:
if([a isEqual: b]) { ...
If a and b are both nil, then they're conceptually equal, but isEqual: still returns false because it's a mindless "always return 0 for messages to nil" thing that doesn't even look at any parameters passed in.
Making messages to nil be a no-op is certainly an "interesting" feature of Objective-C. It can make some code a lot more convenient to write, but it can also make certain bugs really difficult to track down.
After having done Swift for a while, I'm a big fan of using an option type so that "reference to object" is a different static type altogether from "reference to object, or nil."
Comments
A similar but arguably more useful version of this is when you have two variables, one of which may be null. Traditionally you issue an if-condition test using the variable user input as the left operand but switching it handles the null case automatically.
Ex:
Objective-C is really fun here. Messages to nil are no-ops which return zero, which for booleans results in false. Thus, the conditional works just fine either way:
If userSuppliedInput is nil, the isEqual: returns false, and it works.It gets really fun when both might be nil:
If a and b are both nil, then they're conceptually equal, but isEqual: still returns false because it's a mindless "always return 0 for messages to nil" thing that doesn't even look at any parameters passed in.Not sure I like the sound of that. It sounds like the floating point wat of "NaN != NaN".
Or the SQL classic:
It's not true or false, ... it's NULL!Making messages to nil be a no-op is certainly an "interesting" feature of Objective-C. It can make some code a lot more convenient to write, but it can also make certain bugs really difficult to track down.
After having done Swift for a while, I'm a big fan of using an option type so that "reference to object" is a different static type altogether from "reference to object, or nil."
Yes, I really like Rust and the way its Option<Box<T>> decays to a nullable pointer.