使用let _ = ...
是否有任何目的?
我见过What's the _ underscore representative of in Swift References?的问题和答案,我知道下划线can be used to represent a variable that isn't needed。
如果我只需要一个元组的值,就像上面链接中的示例一样,这是有意义的:
let (result, _) = someFunctionThatReturnsATuple()
但是,我最近遇到了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
}
如果我删除let _ =
,我不会收到任何编译器警告或错误。在我看来,这样更简单,更易读。
try DB.run( table.create(ifNotExists: true) {t in
t.column(teamId, primaryKey: true)
t.column(city)
t.column(nickName)
t.column(abbreviation)
})
代码的作者写了a book and a blog about Swift。我知道作者并非万无一失,但它让我想知道是否有一些我遗漏的东西。
答案 0 :(得分:9)
如果方法已使用developer documentation中的warn_unused_result
标记,您将收到编译器警告:
将此属性应用于方法或函数声明,以使编译器在调用方法或函数时发出警告而不使用其结果。
您可以使用此属性提供有关错误使用具有变异对应方式的非突变方法的警告消息。
答案 1 :(得分:7)
使用let _ = ...
专门告诉编译器您知道右侧的表达式返回一个值,但您并不关心它。
如果方法已标记为warn_unused_result
,如果您不使用下划线,则编译器会发出警告。 (因为在某些情况下,不使用返回值可能会出错。)
答案 2 :(得分:4)
有时使用do-catch
比try?
更简单,更清晰,当你调用抛出的东西时,却决定不处理任何错误。如果你按原样与_
保持联系,编译器会警告你未使用的结果,这是不好的。因此,您可以使用let _ = try? NSFileManager.defaultManager().moveItemAtURL(url1, toURL: url2)
放弃结果。
示例:
import time
formattedTime = datetime.datetime(3000, 12, 03)
formattedTime = formattedTime.date().isoformat()
a = 1
b = 2
c = 4
cursor.execute("INSERT INTO nodeStatistics VALUES(%s, %d, %d, %d, NULL, NULL, NULL, NULL, NULL, NULL, 'item1 item2 item3')" %(formattedTime, a, b, c))
cnx.commit()
答案 3 :(得分:4)
此外,当表达式的右侧是let _ =
变量并且您希望现在就对其进行计算时,可以使用_ =
或lazy
,但此变量的值尚未使用
惰性存储属性是其初始值不是 直到第一次使用时才进行计算。您表示一个懒惰存储 属性,方法是在其声明之前编写lazy修饰符。
当属性的初始值为 取决于外部因素,其值直到 实例的初始化已完成。惰性属性也很有用 当属性的初始值需要复数或 除非或,否则不应执行计算量大的设置 直到需要它为止。
示例:
final class Example {
private func deepThink() -> Int {
// 7.5 million years of thinking
return 42
}
private(set) lazy var answerToTheUltimateQuestionOfLifeTheUniverseAndEverything: Int = deepThink()
func prepareTheAnswer() {
_ = answerToTheUltimateQuestionOfLifeTheUniverseAndEverything
}
func findTheQuestion() -> (() -> Int) {
// 10 millions of thinking
let theQuestion = {
// something
return self.answerToTheUltimateQuestionOfLifeTheUniverseAndEverything
}
return theQuestion
}
}
let example = Example()
// And you *want* to get the answer calculated first, but have no use for it until you get the question
example.prepareTheAnswer()
let question = example.findTheQuestion()
question()
答案 4 :(得分:2)
struct ContentView: View {
var body: some View {
let _ = print("View was refreshed")
Text("Hi")
}
}
<块引用>
视图已刷新
您可以使用它来查看属性的当前值:
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")
}
}
}
<块引用>
视图已刷新,currentValue 为 0
视图已刷新,currentValue 为 1
视图已刷新,currentValue 为 2
视图已刷新,currentValue 为 3
视图已刷新,currentValue 为 4
如果你只是做了_ = print(...)
,它不会工作:
struct ContentView: View {
var body: some View {
_ = print("View was refreshed") /// error!
Text("Hi")
}
}
<块引用>
类型'()'不能符合'View';只有 struct/enum/class 类型才能符合协议
答案 5 :(得分:1)
如果有时不需要结果,也可以在自己的函数中使用@discardableResult
。
@discardableResult
func someFunction() -> String {
}
someFunction() // Xcode will not complain in this case
答案 6 :(得分:0)
if let _ = something {
...
}
等于
if something != nil {
...
}
如果您用属性名称替换下划线,则Xcode建议的修复是第二个选项(它不建议第一个)。那是因为第二个选项更有意义。但是,这是Apple自己对开发人员的要求,编写最易读的代码。而且我怀疑下划线选项的存在,因为在某些情况下下划线选项可能比其他选项更好。