为什么我的 Swift 三元运算符不起作用?

Why is my Swift ternary operator not working?

我在学习 Swift 的第二天,我对三元运算符有以下疑问。

我有以下代码:

var list = [2, 4, 3, 6, 1, 9]

var sumOfEven = 0
var productOfOdd = 1

for item in list {
  item % 2 == 0 ? sumOfEven += item : productOfOdd *= item
}

这很容易解释,但为了避免任何疑问,程序应该将 Int 数组中的所有偶数相加,然后将所有奇数相乘。

然而,当我 运行 以上代码时,我有以下代码:

error: result values in '? :' expression have mismatching types '()' and 'Int'
  (item % 2 == 0) ? sumOfEven += item : productOfOdd *= item

我怎么会有不匹配的类型?!我已经尝试将 sumOfEvenproductOfOdd 声明为 IntDouble 但仍然不起作用...

如果我将 If...Else 替换为:

,一切正常
for item in list {
  if item % 2 == 0 {
    sumOfEven += item
  } else {
    productOfOdd *= item
  }

编译器需要一点帮助,由于运算符优先级在语言中的实现方式,三元中的空格导致它变得混乱。如果您将语句括在括号中,那么它将编译并执行您期望的操作。

还有 属性 可以让你检查某物是否是倍数(的:),它可以使代码更容易阅读,但如果你愿意,你可以使用 item % 2 == 0它仍然有效。

var list = [2, 4, 3, 6, 1, 9]

var sumOfEven = 0
var productOfOdd = 1

for item in list {
    item.isMultiple(of: 2) ? (sumOfEven += item) : (productOfOdd *= item)
}

print(sumOfEven)     // 12
print(productOfOdd)  // 27

但是,三元代码会使代码更难理解。这最好写成 if-else 就像你在问题中写的那样。

for item in list {
    if item % 2 == 0 {  // you could use item.isMultiple(of: 2) 
        sumOfEven += item
    } else {
        productOfOdd *= item
    }
}

通常认为使用三元运算符 只有在 没有 副作用 时,例如涉及突变或打印。如果它只是将表达式的值评估为 A 或 B,那么你没问题。你可以这样做:

let list = [2, 4, 3, 6, 1, 9]
let (sumsOfEven, productOfOdd) = list.reduce((0, 1)) { (result, item) in
item.isMultiple(of: 2) ?
    (result.0 + item, result.1) : (result.0, result.1 * item)
}

我会说,每次你去使用三元运算符时,停下来问问自己,它是否让代码更易于遵循和维护?从答案是否定的假设开始,仅在确实提高可读性的情况下使用它。

我要避免的一件事是像您给出的示例那样具有副作用的情况(如果表达式为真,它会添加到 sumOfEvent,如果为假,它会将 productOfOdd 乘以某个值。)

相反,在这种情况下使用它:

var useFirst = true

var firstAddend = 1
var secondAddend = 2

let aValue += useFirst ? firstAddend : secondAddend

但前提是它使代码更清晰、更易于维护。

是否比

更清楚
if useFirst {
    addValue += firstAddend
} else {
    addValue += secondAddend
}

(不是真的,不是。)


编辑

在上面的示例中,三元运算符版本的一个参数是 DRY(不要重复自己)原则。在if/else版本中,变量addValue出现了两次。如果在将来的某个日期更改该变量,则必须记住在两个地方都更改它,否则就有引入错误的风险。我个人认为在这种情况下,可读性更为重要,并且发现 if/else 版本更易于阅读。 (而且我已经专业地使用包含三元运算符的类 C 语言进行编程 ≈35 年了。)