【问题标题】:Make Optional.none evaluate to 0使 Optional.none 评估为 0
【发布时间】:2019-02-11 14:43:58
【问题描述】:

默认情况下,与 nil / NULL 不同的可选值不能与数值进行比较。必须采取哪些步骤才能拥有,例如nil < 1nil < 1.0 评估为真?

【问题讨论】:

  • (optionalVar ?? 0) == 0?
  • 我认为在 Swift 3 中删除了与 nil 的可选比较:github.com/apple/swift-evolution/blob/master/proposals/…
  • @PaulPeelen:您仍然可以测试 equality 的可选项(如果底层类型允许的话)——只有 < 和朋友的可选项已被删除。当然nil 永远不会比较等于非零值。
  • ... 来自 SE-0121:接受可选操作数的 == 和 != 的变体仍然有用,而且它们的结果并不令人惊讶,因此它们将保留。跨度>
  • 这样的比较真的没有意义。离说“我可以采取哪些步骤来制作"Bob" < "Alice"?”不远了。答案不是编辑String 类型,而是做一个更好的比较器。为了比较选项,我made this.

标签: swift null optional


【解决方案1】:

nil == 0 永远不会评估为真,因为它是假的。类似地,1 == 0 不会评估为 true,并且您无法采取任何合理的步骤来做到这一点。 == 不应该返回 true。

你想要的语法是(nil ?? 0) == 0,没错。

但是,如果您发现自己经常尝试将 nil 视为 0(经常需要进行一些特殊处理),那么这表明您的类型不正确。为什么这个变量是可选的?听起来这个变量首先应该只是一个 Int 。如果它作为 Optional 进入您的系统(最常见的是通过 JSON),您应该尽早将其转换为非 Optional 类型,并在系统的其余部分使用它。 Swift 中的绝大多数变量和属性都不应该是可选的。如果是(而且很多人都犯了这个错误),你会发现自己一直在与系统作斗争。


在您的编辑中,Swift 曾经允许您以这种方式将 < 与 nil 一起使用。它被故意删除(SE-0121),因为它会导致很多非常微妙的错误(就像将 NULL 隐式处理为 0 长期以来导致 C 和 ObjC 中的错误一样)。你绝对不应该尝试把它放回去。这是一个非常糟糕的语义。

【讨论】:

  • 你是对的,罗布。我很欣赏你非常合理的回应。我希望有一个可以为 Optional 编写的扩展,例如符合 Comparable 或 Numeric 不仅可以防止工程师不得不编写 (nil ?? 0)(诚然这不是那么繁重),而且还可以让 Swift 像它的前身 Objective-C 一样更像 C。
  • 你不应该期望通过这种方式让 Swift 更像 C。 Swift 的类型系统直接响应了 C 的隐式和模糊转换的许多问题。他们故意删除了这个,因为它在 C 和 ObjC 中造成了很多错误。
  • @IliasKarim 我认为您将 nil 视为 0 可能是错误的。很少有情况真正有意义。如果用户没有输入他们的年龄,则他们的年龄不是 0。如果当前没有 gps 坐标,the coord is not 0。此外,让 Swift 更像 C 语言根本不应该是一个目标。 C 高度关注硬件的工作原理,并驱使程序员围绕它进行设计。它没有高级程序设计的抽象。
  • 是的,我想撤消对可能被视为隐式或模棱两可转换的响应。在许多应用程序中,通常来自系统框架的 nil 值可以合理地预期为非 nil。以UIApplication 上的keyWindow 为例。当默认值为 0 时,展开这些值只会有助于样板文件。
  • 我不明白这个关于keyWindow 的评论。 keyWindow 为零是完全合法的,您经常需要处理这个事实。在应用程序完成启动之前为零,我看到有几个人因为假设他们的代码在那时无法运行而产生错误(这是不正确的;有各种各样的用户代码甚至 UI 代码都可以在之前运行应用程序完成启动;状态恢复因此而臭名昭著)。另外,keyWindow 不是 Int,那么这有什么帮助呢?什么样板会涉及到这个?
【解决方案2】:

我不确定我是否会推荐这样做,但你可以这样做,例如整数首先检查它是否为 nil,如果是,则与 0 进行比较。你必须重复此操作才能翻转参数和其他类型相同。

extension Optional where Wrapped == Comparable {
    public static func < (lhs: Wrapped?, rhs: Int) -> Bool {
        guard let left = lhs as? Int else {
            return 0 < rhs
        }
        return left < rhs
    }
}

【讨论】:

  • 感谢 Tyler,我能够让它工作,但不是作为扩展,而是作为通用函数。
猜你喜欢
  • 2016-08-25
  • 1970-01-01
  • 2019-05-24
  • 2012-09-11
  • 2021-11-01
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
  • 2018-08-16
相关资源
最近更新 更多