为什么我的 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
我怎么会有不匹配的类型?!我已经尝试将 sumOfEven
和 productOfOdd
声明为 Int
和 Double
但仍然不起作用...
如果我将 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 年了。)
我在学习 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
我怎么会有不匹配的类型?!我已经尝试将 sumOfEven
和 productOfOdd
声明为 Int
和 Double
但仍然不起作用...
如果我将 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 年了。)