Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift, Optional wrappers. "?" "!" I understand how it works. But why is it better than != nil checking

I understand how "!" or "?" works. But i'm not quite sure what the added benefit is compared to != nil checking. What is the added benefit of moving to "!?"? I feel like it's just something Apple has added but can't really see the extra benefit compared to status quo of iOS. Am i missing something here? Thanks in advance.

like image 862
shle2821 Avatar asked Mar 13 '15 16:03

shle2821


2 Answers

The difference between checking for nil and requiring an optional being unwrapped can amount to the difference between your code crashing or not. Optionals, when used correctly, can both increase safety and make your code more readable.

Suppose you have an array, and you want to get out the first value in it. You might do it like this:

if !arr.isEmpty {
    useValue(arr[0])
}

But of course, it’s easy to forget that isEmpty part, and if you do, your code will crash with an out-of-bounds error.

So intead, there’s a much better way: use the array's first method, which returns an optional with nil if the array is empty:

if let val = arr.first {
    useValue(val)
}

With this form, you cannot get this wrong. It’s impossible to use the arr. first value without unwrapping it. If you forget, you get a compilation error. It’s also more readable to my eyes/

Presumably you would expect your != nil formulation to work something like this:

if arr.first != nil {
    // all optionals would be “implicit”
    useValue(arr.first)
}

Putting aside that you’re calling .first twice which is a bit inefficient, and the question of type compatibility, essentially this lands you back to square one – you could forget to do the nil comparison, and then, kaboom. Or, you could take the Objective-C approach and say nil is fine to send messages to – but that also leads to all kinds of confusion (personally I hate the idea of an implicit sending messages to nil meaning no-op), and also leads to the question, what do you do when the function returns a value type such as an Int. Must everything be nullable? This leads to much mess in Obj-C land.

What’s more, there are all sorts of conveniences you can introduce once you are dealing with optionals, such as nil-coalescing:

// default to 0 if no first element
arr.first ?? 0
// much neater than this equivalent form:
arr.first != nil ? arr.first : 0

or optional comparison:

// will only be true if arr is non-nil and zero
if arr.first == 0 {

}

For more examples, see this answer

like image 56
Airspeed Velocity Avatar answered Nov 16 '22 20:11

Airspeed Velocity


The ? operator is very convenient, when it comes to chaining, e.g.:

a?.b?.c?.doSomething()

Otherwise you would have to check a, b and c for nil, which may result in more unreadable code than chaining does.

Another thing is, that you can easily mark arguments being optional, e.g.

func someFunc(arg: Type?)

and it is immediately clear, that this is a type which may be nil, i.e. the language enforces this. Otherwise you would pass something which could be nil and you forget the check and experience crashes.

like image 5
Sebastian Dressler Avatar answered Nov 16 '22 20:11

Sebastian Dressler