【问题标题】:Why can't Swift's greater-than or less-than operators compare optionals when the equality operators can?为什么 Swift 的大于或小于运算符不能比较可选项,而相等运算符可以呢?
【发布时间】:2017-06-28 16:48:06
【问题描述】:

在 Swift 3 中,如果我使用 ><,这是一个编译错误

let a: Int?
guard a > 0 else {return}
guard a < 0 else {return}

编译错误:

可选类型“Int?”的值未拆封;你的意思是用'!'还是“?”?


但如果我与==!= 进行比较,就可以了

let a: Int?
guard a == 0 else {return}
guard a != 0 else {return}

【问题讨论】:

标签: swift optional


【解决方案1】:

等式运算符支持可选项是非常有意义的,因为绝对清楚对于任何整数值变量i

  • nil == nil
  • nil != i
  • i != nil
  • i == i 当且仅当它们的值相同时

另一方面,与nil 的比较应该如何发挥作用尚不清楚:

i 是否小于 nil

  • 如果我想对数组进行排序以使所有nils 出现在最后,那么我希望i 小于nil
  • 但是,如果我想对数组进行排序,以便所有nils 从一开始就出现,那么我希望i 大于nil

由于其中任何一个都同样有效,因此标准库偏爱其中一个是没有意义的。由程序员来实现对他们的用例有意义的任何比较。

这是一个玩具实现,它生成一个比较运算符来适应任何一种情况:

func nilComparator<T: Comparable>(nilIsLess: Bool) -> (T?, T?) -> Bool {
    return {
        switch ($0, $1) {
            case (nil, nil): return false
            case (nil, _?): return nilIsLess
            case (_?, nil): return !nilIsLess
            case let (a?, b?): return a < b
        }
    }
}

let input = (0...10).enumerated().map {
    $0.offset.isMultiple(of: 2) ? Optional($0.element) : nil
}

func concisePrint<T>(_ optionals: [T?]) -> String {
    return "[" + optionals.map { $0.map{ "\($0)?" } ?? "nil" }.joined(separator: ", ") + "]"
}

print("Input:", concisePrint(input))
print("nil is less:", concisePrint(input.sorted(by: nilComparator(nilIsLess: true))))
print("nil is more:", concisePrint(input.sorted(by: nilComparator(nilIsLess: false))))

输出:

输入:[0?, nil, 2?, nil, 4?, nil, 6?, nil, 8?, nil, 10?]

nil 小于:[nil, nil, nil, nil, nil, 0?, 2?, 4?, 6?, 8?, 10?]

nil 更多:[0?, 2?, 4?, 6?, 8?, 10?, nil, nil, nil, nil, nil]

【讨论】:

    【解决方案2】:

    可选相等在逻辑上有效,而比较则无效。

    • 5 == 5 = true
    • 5 == nil = false
    • 5 == 6 = false
    • nil == nil = true

    这些都是有道理的,但这些都没有:

    • 6 &gt; 5 = true
    • 5 &gt; 5 = false
    • 5 &gt; nil = ??
    • nil &gt; 5 = ??

    这种类型的比较没有简单的答案,根据用例的不同,答案也不相同。

    【讨论】:

    • 5 &gt; nil = nil nil &gt; 5 = nil 我希望在这种情况下返回类型是 Bool?,而不是 Bool
    【解决方案3】:

    这是因为IntInt? 是两个不同的东西。

    根据documentationInt&lt;&gt;等一些操作符的重载,而Optional只有==!=的重载,见documentation on Optional部分谈论比较可选值

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-16
      • 2015-10-18
      • 2016-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多