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不为真?
答案 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}的原因} {是真实的是z3
是x
而不是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)
)。
顺便说一下,对此的变化也可用于探究作业左侧发生的一些细微之处,这是nil
和nil
个案之间的唯一区别。例如,您可以看到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