@ réponse J.beenie traite votre première question gentiment (et de manière convaincante). b == c
ne sera pas appelé puisque votre one
initial ne correspond pas à 0
, un AND
court-circuit classique.
Votre deuxième question dépend de l'implémentation de ==
pour les tuples. Selon a comment to this question cela fait partie de la langue Swift depuis 2.2.1 et l'implémentation standard serait bien sûr en court circuit car c'est la chose la plus rapide à faire. Donc, dans votre deuxième cas, le deuxième élément ne serait pas comparé.
Btw: Vous n'avez pas besoin de break
dans une instruction Swift , au lieu de fallthrough
si vous le souhaitez.
Correction: Ma proposition s'est révélée être seulement à moitié correcte. Pattern correspondant dans les déclarations switch
semble faire plus que ce à quoi je m'attendais. J'ai essayé de pirater ==
en utilisant mon propre Bool
ENUM (à peu près suivant this post (et ajustement pour Swift 3)) et a obtenu des résultats surprenants:
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
}
}
qui donne
evaluate ==
second case
à quel point j'étais majorly surpris. L'évaluation unique de ==
pour MyBool
valeurs provient de la clause where b == c
dans la première case
et toutes les tuple « comparaisons » ne pas utiliser la fonction MyBool
==
du tout !!Je me doutais bien l'optimisateur interférait donc je me suis tourné le switch
en func
comme
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")
}
}
qui devrait empêcher l'optimisation excessive au moment de la compilation, mais quand je demande maintenant
match((1, .myTrue, .myTrue))
match((1, .myTrue, .myFalse))
match((0, .myTrue, .myFalse))
je reçois
evaluate ==
first case
evaluate ==
second case
default
où le evaluate ==
proviennent encore que de la première case
. Donc, la seule conclusion raisonnable semble être qu'il y a "une autre magie" qui se passe pendant la correspondance de modèle dans les instructions switch
. J'ai essayé de google si je pouvais comprendre ce que c'était, mais en vain jusqu'à présent. De toute façon, il semble y avoir plus de court-circuit que je ne l'aurais cru.
Il est cool d'écrire du code pour prouver la deuxième déclaration de cas également des courts-circuits. Je n'arrive pas à comprendre comment le faire. –
@ J.beenie vous avez raison, il semble y avoir quelque chose d'autre, la correspondance des motifs semble être * vraiment bien optimisé * (TM) dans Swift. Voyons s'il y a quelqu'un qui peut faire la lumière sur cela. – Patru