【问题标题】:Warning for ternary conditional operator only occurs at local scope三元条件运算符的警告仅在本地范围内发生
【发布时间】:2017-02-17 10:54:13
【问题描述】:

我使用以下 Swift 代码根据单位值设置键字符串:

let units = 0
let key = units == 0 ? "F" : "C"
// this example makes key = "F"

上面的例子在 Swift 文件的全局范围内可以正常工作,没有任何警告。但是,当我将相同的代码放入初始化程序或函数中时,我会收到涉及“C”术语的警告:

struct Almanac {
    // properties
}

extension Almanac {

    init?(json: [String: Any]) {
        let units = 0
        let key = units == 0 ? "F" : "C"  // WARNING: Will never be executed

        // ...
    }

}

func logunits() {
    let units = 0
    let key = units == 0 ? "F" : "C"  // WARNING: Will never be executed
    print("key is \(key)")
}

为什么只有在本地范围内使用三元条件时才会出现此警告?

【问题讨论】:

  • 据我所知,这与失败的初始化器无关——如果你只是将代码放在一个函数中,你会得到同样的警告。只有当它位于 main.swift 文件或 Playground 的顶层时,它才不会给你警告(无论是否有意,我不能说)
  • @Hamish 根据您的评论,我修改了我的问题。我仍然想知道为什么操作符的范围会导致警告。

标签: swift struct initialization conditional-operator


【解决方案1】:

这与作用域有关,因为在某些给定作用域中,编译器能够解析这个简单的表达式并看到某些部分不会被执行。

有了这个:

func logunits() {
    let units = 0
    let key = units == 0 ? "F" : "C"
    print("key is \(key)")
}

编译器在同一范围内具有units = 0 和units == 0 ?,因此它能够解析路径(因为没有任何东西会改变两行之间units 的值)并告诉你是的,确实,单位是 0,是的,“C”将始终被忽略。

如果更改值:

func logunits() {
    let units = 1
    let key = units == 0 ? "F" : "C"
    print("key is \(key)")
}

警告突然从“C”跳到“F”。 :)

如果你把值放在范围之外:

let units = 0

func logunits() {
    let key = units == 0 ? "F" : "C"
    print("key is \(key)")
}

警告消失。

请注意,如果路径中有任何代码可以更改units 的值,即使是像本例中这样的愚蠢代码,警告也会消失:

func logunits() {
    var units = 0
    if true { units = 1 }
    let key = units == 0 ? "F" : "C"
    print("key is \(key)")
}

【讨论】:

  • 那么为什么它能够在某些情况下检查值而在其他情况下不能检查?
  • @wigging 因为在某些情况下,它可以看到没有任何东西会改变值,比如当它在本地范围内并且两行是连续的时。如果你告诉编译器“嘿,这有一个零值,哦顺便说一句,哪个是值,所以我可以选择这个其他的东西?”它会回答“嗯,它是零,正如你之前所说的那样......”。如果你引入任何可以改变值的东西,这个特性就会停止工作——因为它只有在上下文是 100% 保证分析值没有突变的情况下才有效。如果值可以在运行时更改,则此编译器功能不适用。
  • @wigging 这就是我所说的resolve the path,看看你的代码流:从函数签名开始,然后是下一行,然后是下一行,然后......这就是路径。如果静态数据在路径中是可分析的,编译器会计算路径。如果数据可以在运行时更改(这是我们编写的大部分代码),则不会。
  • 好的,我现在明白了,谢谢你的解释。
猜你喜欢
  • 2016-05-06
  • 2016-11-08
  • 2017-09-14
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 2016-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多