swift中奇怪的可选值使用

时间:2014-06-05 06:38:26

标签: swift optional

    var z1 = false
    var z2 = false
    var z3 = false


    if let y1: Int = nil {
        z1 = true
    }

    if let y2: Int? = nil {
        z2 = true
    }

    var x: Int? = nil
    if let y3: Int? = x {
        z3 = true
    }

    println(z1)   // false
    println(z2)   // ture
    println(z3)   // false

我尝试使用这样的可选值(我知道这是经过的,我只是对深度中的可选值感到好奇)。

重新开始并不像我期望的那样。 z1是假的,这是我预期的,但为什么z2是真的? 赋值后y2为nil,但是if语句认为这个表达式(let y2: Int? = nil)为真,并且下一个语句被执行(z2=true),为什么会发生这种情况?

为什么z2不是假的?

如果y2刚刚声明为可选值,可以包含anther可选值,并且可选值可能为nil,if let语句只是检测到unwrap是否成功,那么,为什么z3不为真?

5 个答案:

答案 0 :(得分:3)

这是因为您可以将可选变量声明为递归可选,如下所示:

var x: Int?? = 5
// LLDB: p x.dynamicType returns (Int??)

你可以走得更远:

var y: Int????????? = 6
// LLDB: p x.dynamicType returns (Int?????????)

if let构造的作用是检查是否可以展开可选值,并且即使它的最终值为nil,也可以解包可选的可选值。可以想象它是可选值本身不是nil,它是包裹nil的一些对象。

要在代码中进行检查,您可以执行以下操作:

var a: Int? = nil;
// LLDB: p a! returns fatal error: Can't unwrap Optional.None

var b: Int?? = nil;
// LLDB: p b! returns (Int?) $R2 = nil

所以这就是你的z2条件发生的情况:if let构造正在检查它是否可以解包y2而它是,所以if块被执行了。 / p>

答案 1 :(得分:1)

可选绑定的工作方式是if检查let声明是否成功。在你的第一个语句中,它是不成功的,因为你不能将nil分配给一个Int,但是在你的第二个语句中它成功并进入正文,因为你被允许将nil分配给一个Int Optional。

答案 2 :(得分:1)

对我而言,z2为false且z3为真:

println(z1)   // false
println(z2)   // false
println(z3)   // true

回顾if let A = optB { ... }本质上意味着“如果optB不是nil将其分配给A并执行以下块”,那么{{1}的原因} {是真实的是z3x而不是Optional(nil)。您可以通过尝试

来看到这一点
nil

并将此版本与原始版本进行比较

var x: Int? = 5
if let y3: Int? = x {
    println(x) // Optional(5)
    z3 = true
}
println(z3)    // true

在第一种情况下,您可以看到var x: Int? = nil if let y3: Int? = x? { z3 = true } println(z3) // false! 被包装(因此原始版本不是x而是nil);在第二个中,您可以看到Optional(nil)如何解包以生成x

Swift(特别是在Xcode Playground中查看)因为它显示nil的方式而难以看清(可能是因为它无法解开,显示nil和{{1} } Optional(nil))。


顺便说一下,对此的变化也可用于探究作业左侧发生的一些细微之处,这是nilnil个案之间的唯一区别。例如,您可以看到z1案例中的z2案例,z3是可选的

z2

y3的类型中删除var x: Int? = 5 if let y3: Int? = x { println(x) // Optional(5) println(y3) // Optional(5) z3 = true } println(z3) // true 时使其与?案例类似,其中y3不是可选的

z1

答案 3 :(得分:0)

因为你错过了一个"?"在z1

答案 4 :(得分:0)

我将尝试解释它添加块注释,以便您可以看到推断的类型和值。

var z1 = false  
var z2 = false  
var z3 = false  


if let y1: Int = nil /* nil : Optional<T>   instantiated to Optional<Int>, value is .None */ 
{
    z1 = true
}

if let y2: Int? = nil /* nil : Optional<T>   instantiated to Optional<Optional<Int>>, value is .Some(.None) */ 
{
    z2 = true
}

var x: Int? = nil   /* nil : Optional<T>   instantiated to Optional<Int>, value is .None */ 
if let y3: Int? = x /* x : Optional<Int>   value is .None */ 
{
    z3 = true
}

println(z1)   // false
println(z2)   // ture
println(z3)   // false