实施"要么" Swift中的struct

时间:2014-07-04 11:51:09

标签: swift

有人可以解释下面代码中发生的事情吗?它创建了一个结构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}

我认为这与“可选的选项”有关,但我不确定它是否符合预期。

1 个答案:

答案 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

在此确认:https://devforums.apple.com/thread/234463?tstart=0