有人可以解释下面代码中发生的事情吗?它创建了一个结构Either
,它接受任意两种可选类型,并且(尝试)返回任何一个不是nil,或者如果两者都不是nil则返回第一个。但是,当传递文字nil而不是nil变量时,它表现得很奇怪。我不明白为什么示例中的b4
表现得像......
struct Either <T1, T2> {
let first: T1?
let second: T2?
init(first: T1?, second: T2?) {
self.first = first
self.second = second
}
func either() -> Bool {
return (self.first != nil) || (self.second != nil)
}
func which() -> Any? {
if self.first != nil {
return self.first
} else if self.second != nil {
return self.second
}
return nil
}
}
var s1: String? = nil
var s2: Int? = nil
let b1 = Either(first: s1, second: s2)
b1.either() // false
b1.which() // {nil}
s1 = "Hello"
let b2 = Either(first: s1, second: s2)
b2.either() // true
b2.which() // {Some Hello}
s1 = nil
s2 = 7
let b3 = Either(first: s1, second: s2)
b3.either() // true
b3.which() // {Some 7}
// all as expected, however
let b4 = Either(first: nil, second: nil)
b4.either() // true !!! <<<<<<<<<<<<<<<<<<
b4.which() // {nil}
我认为这与“可选的选项”有关,但我不确定它是否符合预期。
答案 0 :(得分:6)
这在Beta 3中得到修复,最后一种情况现在正确触发了编译器错误,迫使您明确指定泛型类型
问题在于类型 - 从文字创建Either
时:
let b4 = Either(first: nil, second: nil)
然后编译器无法推断nil
参数的类型。如果检查调试器,您将看到推断类型是一个名为_Nil
的类型。
(lldb) p b4
(SwiftConsole.Either<_Nil, _Nil>) $R1 = {
first = Some
second = Some
}
现在,这是一个接受nil
但它本身不是可选类型的类型。
let x: _Nil = nil //this is not an optional
初始化程序会对其进行选择,从而生成值Optional.Some(nil)
,因为它是.Some(...)
值,将其与nil
进行比较将为false
。
我没有看到任何简单的通用解决方法,但在这种情况下,它将有助于明确指定泛型类型:
let b4 = Either<String, Int>(first: nil, second: nil)
我建议您举报错误,因为这很愚蠢。
而不是推断一些导致未定义行为的特殊类型,而不是引发错误。类型Any
会出现同样的问题,因为它也可以接受nil
而不是可选项。
let x: Any = nil //this is not an optional
Either<Any, Any>(first: nil, second: nil).which() //true !!!
修改:
这将在Beta 3中得到修复。nil
将被视为文字,_Nil
类型将被删除,_Any
将不再接受nil
。