对嵌套合并运算符的困惑

时间:2017-02-20 18:43:10

标签: swift optional

我最近遇到了这段代码。

let s1: String?? = nil
(s1 ?? "inner") ?? "outer" // Prints inner





let st2: String?? = .some(nil)
(st2 ?? "inner") ?? "outer" // prints outer

不确定为什么(s2 ?? "inner")返回nil。对此完全糊涂了。有人可以帮我理解原因。

2 个答案:

答案 0 :(得分:2)

最初忽略nil合并运算符的组合使用:当使用嵌套的可选类型工作(出于某种原因)时,明确键入类型(而不是使用公共{{1})会很有帮助每个可选“级别”的语法糖)。 E.g:

?

使用显式类型的嵌套可选(let s1: Optional<Optional<String>> = nil /* ^^^^^^^^^................^- 'nil' with regard to "outer" optional */ let s2: Optional<Optional<String>> = .some(nil) /* ^^^^^^^^^................^- the "outer" optional has value .some(...), i.e, not 'nil' which would be .none. ^^^^^^^^^^^^^^^^-the "inner" optional, on the other hand, has value 'nil' (.none) */ )并分析上述两个不同的赋值,我们可以继续评估每个实例上的两个组合String??合并运算符调用。很明显:

nil

理解稍微棘手的let foo1 = (s1 ?? "inner") ?? "outer" // equals "inner" /* ^^- is 'nil', hence the call to 's1 ?? "inner" will coalesce to "inner", which is a concrete 'String' (literal), which means the second nil coalescing operator will not coelesce to "outer" */ let foo2 = (s2 ?? "inner") ?? "outer" // equals "outer" /* ^^- is .some(...), hence the call to 's1 ?? "inner" will coalesce to _the concrete value wrapped in 's1'_; namely 'nil', due some, .some(nil). hence, (s1 ?? "inner") results in 'nil', whereafter the 2nd nil coalescing call, 'nil ?? "outer"', will naturally result in 'outer' */ 案例的关键是将s2合并运算符应用于nil 的lhs(左侧)将始终导致 .some(...)包含的值,即使包装的值本身恰好是.some(...)(或nil)。

.none

如果我们选择查看the stdlib implementation of the nil coalescing operator

,这也很明显
Optional<SomeType>.some(someThing) ?? anotherThing
// -> someThing, even if this happens to be 'nil'

答案 1 :(得分:2)

let st2: String?? = .some(nil) 
(st2 ?? "inner") ?? "outer" // prints outer
     

不确定为什么(s2 ??“内部”)返回nil

因为那是你放在那里的:

let st2: String?? = .some(nil)
                          ^^^

比较

let st2: String?? = .some("howdy")
(st2 ?? "inner") ?? "outer" // prints howdy