具有多个评估的switch语句是否短路?
这可能并不重要,但我很好奇。
这是一个简单的例子:
let one = 1
let two = true
let three = false
switch (one, two, three) {
case let (0, b, c) where b==c:
break
case (0, true, true):
break
default:
break
}
在第一个案例陈述中,'其中'评估甚至发生了?
在第二个案例陈述中,'两个' ==真的发生了?
答案 0 :(得分:2)
@ J.beenie的回答很好地(令人信服地)对待你的第一个问题。由于您的初始b == c
与经典one
短路0
不符,因此不会调用AND
。
您的第二个问题取决于==
对元组的实现。根据{{3}},这是自2.2.1以来Swift语言的一部分,标准实现当然会短路,因为它是最快的事情。所以在你的第二种情况下,不会比较第二个元素。
顺便说一下:你不需要在break
语句中使用switch
,如果你不愿意,你可以fallthrough
。
<强>校正:强>
我的猜测证明只有一半是正确的。 switch
语句中的模式匹配似乎比我预期的要多。我试图使用我自己的==
枚举来劫持Bool
(大致跟随a comment to this question(并调整为Swift 3))并得到了一些令人惊讶的结果:
import Cocoa
let one = 1
let two:MyBool = .myTrue
let three:MyBool = .myFalse
typealias ThreeTuple = (o:Int, tw:MyBool, th:MyBool)
let tuple:ThreeTuple
tuple = (one, two, three)
switch tuple {
case let (1, b, c) where b == c:
print("first case")
case (1, .myTrue, .myFalse):
print("second case")
default:
print("default")
}
enum MyBool : ExpressibleByBooleanLiteral, Equatable {
case myTrue, myFalse
public init() { self = .myFalse }
public init(booleanLiteral value: BooleanLiteralType) {
self=value ? .myTrue : .myFalse
}
}
func ==(lhs: MyBool, rhs: MyBool) -> Bool {
print("evaluate ==")
switch (lhs, rhs) {
case (.myTrue,.myTrue), (.myFalse,.myFalse):
return true
default:
return false
}
}
产生
evaluate ==
second case
此时我非常惊讶。对==
值MyBool
的唯一评估来自第一个where b == c
中的case
子句以及所有元组&#34;比较&#34};不要使用MyBool
==
函数 !!我怀疑优化器正在干扰,因此我将switch
转换为func
func match(_ tuple:ThreeTuple) {
switch tuple {
case let (1, b, c) where b == c:
print("first case")
case (1, .myTrue, .myFalse):
print("second case")
default:
print("default")
}
}
这应该排除编译时的过度优化,但是当我现在要求
时match((1, .myTrue, .myTrue))
match((1, .myTrue, .myFalse))
match((0, .myTrue, .myFalse))
我得到了
evaluate ==
first case
evaluate ==
second case
default
其中evaluate ==
仍然仅来自第一个case
。因此,唯一合理的结论似乎是有一些其他的魔法&#34;在switch
语句中的模式匹配期间继续。我试图谷歌,如果我能弄清楚那是什么,但到目前为止无济于事。无论如何,似乎 way 比我预期的更短路。
答案 1 :(得分:1)
使用以下代码测试您的问题:
let one = 1
let two = true
let three = false
switch (one, two, three) {
case let (0, b, c) where b - c:
break
case (0, true, true):
break
default:
break
}
extension Bool{
static func - (lhs: Bool, rhs: Bool) -> Bool {
print("foo")
return lhs == rhs
}
}
在操场上
只需将前0改为1,看看会发生什么。
答案是肯定的;)它确实短路。