做Swift Switch短路吗?

做Swift Switch短路吗?

问题描述:

开关语句有多个评估短路吗?做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会发生吗?

@ 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

测试你用下面的代码问题:

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,看看会发生什么。

答案是肯定的;)确实短路。