Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does "let _ = ..." (let underscore equal) have any use in Swift?

Tags:

ios

swift

Does using let _ = ... have any purpose at all?

I've seen question and answers for What's the _ underscore representative of in Swift References? and I know that the underscore can be used to represent a variable that isn't needed.

This would make sense if I only needed one value of a tuple as in the example from the above link:

let (result, _) = someFunctionThatReturnsATuple()

However, I recently came across this code:

do {
    let _ = try DB.run( table.create(ifNotExists: true) {t in
        t.column(teamId, primaryKey: true)
        t.column(city)
        t.column(nickName)
        t.column(abbreviation)
        })

} catch _ {
    // Error throw if table already exists
}

I don't get any compiler warnings or errors if I just remove the let _ =. It seems to me like this is simpler and more readable.

try DB.run( table.create(ifNotExists: true) {t in
    t.column(teamId, primaryKey: true)
    t.column(city)
    t.column(nickName)
    t.column(abbreviation)
    })

The author of the code has written a book and a blog about Swift. I know that authors aren't infallible, but it made me wonder if there is something I am missing.

like image 577
Suragch Avatar asked Apr 19 '16 08:04

Suragch


4 Answers

It's also useful to print() something in SwiftUI.

struct ContentView: View {
    var body: some View {
        let _ = print("View was refreshed")
        Text("Hi")
    }
}

View was refreshed

You can use it to see the current value of properties:

struct ContentView: View {
    @State var currentValue = 0

    var body: some View {
        let _ = print("View was refreshed, currentValue is \(currentValue)")
        Button(action: {
            currentValue += 1
        }) {
            Text("Increment value")
        }
    }
}

View was refreshed, currentValue is 0
View was refreshed, currentValue is 1
View was refreshed, currentValue is 2
View was refreshed, currentValue is 3
View was refreshed, currentValue is 4

If you just did _ = print(...), it won't work:

struct ContentView: View {
    var body: some View {
        _ = print("View was refreshed") /// error!
        Text("Hi")
    }
}

Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols

like image 99
aheze Avatar answered Sep 21 '22 20:09

aheze


You will get a compiler warning if the method has been marked with a warn_unused_result from the developer documentation:

Apply this attribute to a method or function declaration to have the compiler emit a warning when the method or function is called without using its result.

You can use this attribute to provide a warning message about incorrect usage of a nonmutating method that has a mutating counterpart.

like image 20
sbarow Avatar answered Oct 17 '22 23:10

sbarow


Using let _ = ... specifically tells the compiler that you know that the expression on the right returns a value but that you don't care about it.

In instances where the method has been marked with warn_unused_result, if you don't use the underscore then the compiler will complain with a warning. (Because in some cases it could be an error to not use the return value.)

like image 7
Suragch Avatar answered Oct 18 '22 00:10

Suragch


Sometimes it is simple and cleaner to use try? than do-catch, when you call something that throws, but decided not to handle any errors. If you leave call with try? as-is, compiler will warn you about unused result, which is not good. So you can discard results using _.

Example:

let _ = try? NSFileManager.defaultManager().moveItemAtURL(url1, toURL: url2)
like image 4
Alexander Doloz Avatar answered Oct 18 '22 00:10

Alexander Doloz