Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between if nil != optional … and if let _ = optional …

Tags:

I need to test if an expression which returns an optional is nil. This seems like a no-brainer, but here is the code.

if nil != self?.checklists.itemPassingTest({ $0 === note.object }) {     … } 

Which, for some reason, looks unpleasant to my eye.

if let item = self?.checklists.itemPassingTest({ $0 === note.object }) {     … } 

Looks much better to me, but I don't actually need the item, I just need to know if one was returned. So, I used the following.

if let _ = self?.checklists.itemPassingTest({ $0 === note.object }) {     … } 

Am I missing something subtle here? I think if nil != optional … and if let _ = optional … are equivalent here.


Update to address some concerns in the answers

  1. I don't see the difference between nil != var and var != nil, although I generally use var != nil. In this case, pushing the != nil after the block gets the boolean compare of block mixed in with the boolean compare of the if.

  2. The use of the Wildcard Pattern should not be all that surprising or uncommon. They are used in tuples (x, _) = (10, 20), for-in loops for _ in 1...5, case statements case (_, 0):, and more (NOTE: these examples were taken from The Swift Programming Language).

This question is about the functional equivalency of the two forms, not about coding style choices. That conversation can be had on programmers.stackexchange.com.


After all this time, Swift 2.0 makes it moot

if self?.checklists.contains({ $0 === note.object }) ?? false {     … } 
like image 332
Jeffery Thomas Avatar asked Mar 28 '15 21:03

Jeffery Thomas


People also ask

What is the difference between optional none and nil?

Question : What's the difference optional between nil and . None? Answer : There is no difference.

What does if let mean in Swift?

The “if let” allows us to unwrap optional values safely only when there is a value, and if not, the code block will not run. Simply put, its focus is on the “true” condition when a value exists.

What is the point of optionals in Swift?

Optional types or Optionals in Swift You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn't a value at all.


2 Answers

After optimization, the two approaches are probably the same.

For example, in this case, compiling both the following with swiftc -O -emit-assembly if_let.swift:

import Darwin  // using arc4random ensures -O doesn’t just // ignore your if statement completely let i: Int? = arc4random()%2 == 0 ? 2 : nil  if i != nil {   println("set!") } 

vs

import Darwin  let i: Int? = arc4random()%2 == 0 ? 2 : nil  if let _ = i {   println("set!") } 

produces identical assembly code:

    ; call to arc4random     callq   _arc4random     ; check if LSB == 1      testb   $1, %al     ; if it is, skip the println     je  LBB0_1     movq    $0, __Tv6if_let1iGSqSi_(%rip)     movb    $1, __Tv6if_let1iGSqSi_+8(%rip)     jmp LBB0_3 LBB0_1:     movq    $2, __Tv6if_let1iGSqSi_(%rip)     movb    $0, __Tv6if_let1iGSqSi_+8(%rip)     leaq    L___unnamed_1(%rip), %rax  ; address of "set!" literal     movq    %rax, -40(%rbp)     movq    $4, -32(%rbp)     movq    $0, -24(%rbp)     movq    __TMdSS@GOTPCREL(%rip), %rsi     addq    $8, %rsi     leaq    -40(%rbp), %rdi     ; call println     callq   __TFSs7printlnU__FQ_T_ LBB0_3:     xorl    %eax, %eax     addq    $32, %rsp     popq    %rbx     popq    %r14     popq    %rbp     retq 
like image 181
Airspeed Velocity Avatar answered Nov 13 '22 19:11

Airspeed Velocity


The if let syntax is called optional binding. It takes an optional as input and gives you back a required constant if the optional is not nil. This is intended for the common code pattern where you first check to see if a value is nil, and if it's not nil (if it has a value), you do something with it.

If the optional is nil, processing stops and the code inside the braces is skipped.

The if optional != nil syntax is simpler. It simply checks to see if the optional is nil. It skips creating a required constant for you.

The optional binding syntax is wasteful and confusing if you're not going to use the resulting value. Use the simpler if optional != nil version in that case. As nhgrif points out, it generates less code, plus your intentions are much clearer.

EDIT:

It sounds like the compiler is smart enough to not generate extra code if you write "if let" optional binding code but don't end up using the variable you bind. The main difference is in readability. Using optional binding creates the expectation that you are going to use the optional that you bind.

like image 44
Duncan C Avatar answered Nov 13 '22 20:11

Duncan C