我最近遇到了這個代碼片段。嵌套合併運算符的混淆
let s1: String?? = nil
(s1 ?? "inner") ?? "outer" // Prints inner
let st2: String?? = .some(nil)
(st2 ?? "inner") ?? "outer" // prints outer
不知道爲什麼(s2 ?? "inner"
)返回nil
。完全困惑於此。有人能幫我理解原因嗎?
我最近遇到了這個代碼片段。嵌套合併運算符的混淆
let s1: String?? = nil
(s1 ?? "inner") ?? "outer" // Prints inner
let st2: String?? = .some(nil)
(st2 ?? "inner") ?? "outer" // prints outer
不知道爲什麼(s2 ?? "inner"
)返回nil
。完全困惑於此。有人能幫我理解原因嗎?
最初不顧結合使用nil
合併運算符的:與嵌套可選類型的工作(由於某種原因)時,它可以幫助明確打出來的類型(而不是使用普通?
語法糖每個可選「水平」)。例如: -
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
情況下的關鍵是與LHS施加nil
合併運算符(左手側)即.some(...)
將總是導致在由包裹值即使包裝值本身恰巧是nil
(或.none
),也是如此。
Optional<SomeType>.some(someThing) ?? anotherThing
// -> someThing, even if this happens to be 'nil'
這也很明顯,如果我們選擇看看the stdlib implementation of the nil
coalescing operator:
public func ?? <T>(optional: T?, defaultValue: @autoclosure() throws -> T)
rethrows -> T {
switch optional {
case .some(let value):
// in your example (s2 and leftmost ?? call), 'T' is Optional<String>,
// and 'value' will have the value 'nil' here (which is a valid return for 'T')
return value
case .none:
return try defaultValue()
}
}
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
我認爲有在代碼的第二塊的錯誤,因爲這兩個foo1和foo2的聲明同樣存在。不應該是「foo2 =(s2 ?? ...」? – nbloqs
@nbloqs是的,謝謝,代表我的錯字! – dfri
我很樂意幫忙! – nbloqs