@ J.beenie的答案很好地(和令人信服地)對待你的第一個問題。 b == c
將不會被調用,因爲您的初始one
不匹配0
,經典AND
短路。
你的第二個問題取決於元組的==
的實現。根據a comment to this question,自從2.2.1版本以來,這已經是Swift語言的一部分,並且標準實現當然是短路的,因爲它是最快速的事情。所以在第二種情況下,第二個元素不會被比較。
順便說一句:你不需要break
在一個Swift switch
聲明,而不是你想fallthrough
,如果你需要的話。
糾錯: 我的猜測證明只是一半正確。在switch
聲明中的模式匹配似乎比我預期的要多。我試圖用我自己的Bool
枚舉(大致如下this post(和調整斯威夫特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
在這一點上,我majorly驚訝。 ==
對MyBool
值的唯一評估值來自第一個case
中的where b == c
子句,並且所有元組「比較」都不使用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
。因此,唯一合理的結論似乎是在switch
聲明中的模式匹配過程中發生了「其他一些魔法」。我試圖谷歌,如果我能弄清楚那是什麼,但目前爲止無濟於事。無論如何,似乎有方式更多的短路超出我的預期。
寫一些代碼來證明第二種情況也是很酷的短路。不能弄清楚如何做到這一點。 –
@ J.beenie你是對的,似乎還有其他事情正在發生,模式匹配似乎在* Swift中*真正優化*(TM)。讓我們看看是否有人能夠對此有所瞭解。 – Patru