L'idiome utilisé pour traiter les options dans Swift semble excessivement détaillé, si vous souhaitez simplement fournir une valeur par défaut dans le cas où il s'agirait de rien:
if let value = optionalValue {
// do something with 'value'
} else {
// do the same thing with your default value
}
qui implique la duplication inutile de code, ou
var unwrappedValue
if let value = optionalValue {
unwrappedValue = value
} else {
unwrappedValue = defaultValue
}
qui nécessite unwrappedValue
ne pas être une constante.
La monade Option de Scala (qui est fondamentalement la même idée que celle de Swift, optionnelle) utilise la méthode getOrElse
à cette fin:
val myValue = optionalValue.getOrElse(defaultValue)
Est-ce que je manque quelque chose? Est-ce que Swift a déjà un moyen compact de le faire? Ou, à défaut, est-il possible de définir getOrElse
dans une extension pour Optional?
Mettre à jour
Apple a maintenant ajouté un opérateur de coalescence:
var unwrappedValue = optionalValue ?? defaultValue
L'opérateur ternaire est votre ami dans ce cas
var unwrappedValue = optionalValue ? optionalValue! : defaultValue
Vous pouvez également fournir votre propre extension pour l'énumération facultative:
extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}
Ensuite, vous pouvez simplement faire:
optionalValue.or(defaultValue)
Cependant, je recommande de s'en tenir à l'opérateur ternaire car les autres développeurs le comprendront beaucoup plus rapidement sans avoir à étudier la méthode or
Remarque : J'ai lancé un module pour ajouter des aides communes comme ceci or
sur Optional
à Swift .
Depuis août 2014, Swift a un opérateur de coalescence (??) qui le permet. Par exemple, pour une chaîne facultative myOptional, vous pouvez écrire:
result = myOptional ?? "n/a"
si vous avez écrit:
let result = optionalValue ?? 50
et optionalValue != nil
puis result
sera aussi optional
et vous devrez le dérouler à l'avenir
Mais vous pouvez écrire opérateur
infix operator ??? { associativity left precedence 140 }
func ???<T>(optLeft:T?, right:T!) -> T!
{
if let left = optLeft
{
return left
}
else { return right}
}
Maintenant vous pouvez:
let result = optionalValue ??? 50
Et quand optionalValue != nil
alors result
sera unwraped
Ce qui suit semble fonctionner
extension Optional {
func getOrElse<T>(defaultValue: T) -> T {
if let value = self? {
return value as T
} else {
return defaultValue
}
}
}
cependant, la nécessité de lancer value as T
est un vilain piratage. Idéalement, il devrait exister un moyen d'affirmer que T
est identique au type contenu dans Optional. En l'état actuel, les ensembles d'inférence de types T
sont basés sur le paramètre donné à getOrElse, puis échouent au moment de l'exécution si cela ne correspond pas à Facultatif et si Facultatif est non nul.
let x: Int?
let y = x.getOrElse(1.414) // y inferred as Double, assigned 1.414
let a: Int? = 5
let b: Double = a.getOrElse(3.14) // Runtime failure casting 5 to Double