2017-04-19 26 views
1

開關語句有多個評估短路嗎?做Swift 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 
} 

在第一個case語句,將在 '地點' 的評價,甚至發生?

在第二種情況下,'two'== true會發生嗎?

回答

2

@ 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==函數根本沒有 !!我懷疑優化器進行干擾,所以我變成了switchfunc作爲

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聲明中的模式匹配過程中發生了「其他一些魔法」。我試圖谷歌,如果我能弄清楚那是什麼,但目前爲止無濟於事。無論如何,似乎有方式更多的短路超出我的預期。

+0

寫一些代碼來證明第二種情況也是很酷的短路。不能弄清楚如何做到這一點。 –

+0

@ J.beenie你是對的,似乎還有其他事情正在發生,模式匹配似乎在* Swift中*真正優化*(TM)。讓我們看看是否有人能夠對此有所瞭解。 – Patru

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,看看會發生什麼。

答案是肯定的;)確實短路。