7

我正在尝试制作一个具有多个值的简单 if-let 语句。if仅当所有可选 var 都非 nil 时才应执行该块,并且应将它们分配给仅存在于该if块内的新 let-var(常量?),就像普通的单赋值 if-let 一样。

var a: String? = "A"
var b: String? // nil

if let (m, n) = (a, b) {
    println("m: \(m), n: \(n)")
} else {
    println("too bad")
}
// error: Bound value in a conditional binding must be of Optional type
// this of course is because the tuple itself is not an Optional
// let's try that to be sure that's the problem...

let mysteryTuple: (String?, String?)? = (a, b)
if let (m, n) = mysteryTuple {
    println("m: \(m), n: \(n)")
} else {
    println("too bad")
}
// yeah, no errors, but not the behavior I want (printed "m: A, n: nil")

// and in a different way:
if let m = a, n = b {
    println("m: \(m), n: \(n)")
} else {
    println("too bad")
}
// a couple syntax errors (even though 'let m = a, n = b'
// works on its own, outside the if statement)

这甚至可能吗?如果不是(我猜),您认为 Apple 将来会(或应该)实现这一点吗?

4

2 回答 2

10

这一点现在可能已经很明显了,但是你对这个预期功能的追求可能会随着 Swift 1.2 的发布而结束。

来自 swift 博客:https ://developer.apple.com/swift/blog/?id=22

使用 if let 进行更强大的可选解包 - if let 构造现在可以一次解包多个可选选项,并且包括中间的布尔条件。这使您可以表达条件控制流,而无需不必要的嵌套。

但它的短处是,除了使用 where 子句限制值之外,您现在可以按照您的要求进行操作。

if let a = foo(), b = bar() {
}
于 2015-05-28T20:45:44.937 回答
8

在决定是否可能之前,请考虑为什么if - let ...条件使用单个可选值:此代码编译的原因

if let constVar = testVar {
    ...
}

是所有可选类型都符合LogicalValue协议,该协议处理可选值的空检查。

这解释了为什么使用可选元组的技巧也不起作用:LogicalValue如果元组本身为非空,则执行检查的实现,忽略其组件。Apple 决定背后的逻辑很清楚:当元组的所有元素类型都是可选的时,他们并没有对元组进行例外处理,而是采用了统一的方法,并以与处理其他可选类型相同的方式处理元组。

当然,通过额外的代码行来实现您尝试实现的逻辑很容易:

if a != nil && b != nil {
    let (m, n) = (a!, b!)
    println("m: \(m), n: \(n)")
} else {
    println("too bad")
}
于 2014-07-18T17:57:01.433 回答