protocol - ¿Proporcionando un valor predeterminado para un Opcional en Swift?
swift syntax (5)
A partir de agosto de 2014, Swift tiene un operador coalescente (??) que permite eso. Por ejemplo, para un String myOptional opcional, podría escribir:
result = myOptional ?? "n/a"
El modismo para tratar opcionales en Swift parece excesivamente detallado, si todo lo que quiere hacer es proporcionar un valor predeterminado en el caso de que sea nulo:
if let value = optionalValue {
// do something with ''value''
} else {
// do the same thing with your default value
}
que implica duplicar código innecesariamente, o
var unwrappedValue
if let value = optionalValue {
unwrappedValue = value
} else {
unwrappedValue = defaultValue
}
que requiere que el valor unwrappedValue
no sea una constante.
La mónada de Scala''s Option (que es básicamente la misma idea que Swift''s Optional) tiene el método getOrElse
para este propósito:
val myValue = optionalValue.getOrElse(defaultValue)
¿Me estoy perdiendo de algo? ¿Swift tiene una forma compacta de hacer eso ya? O, en su defecto, ¿es posible definir getOrElse
en una extensión para Opcional?
He creado una biblioteca de extensión simple y la uso para reducir esos códigos repetitivos. Echa y devuelve tipos primitivos opcionales en valor predeterminado. Usted acaba de lanzarlo como a continuación,
CGFloat(optionalValue)
o con cierto valor predeterminado,
Int(optionalValue, defaultValue: 100)
Puedes mirar a través de this repositorio.
Lo siguiente parece funcionar
extension Optional {
func getOrElse<T>(defaultValue: T) -> T {
if let value = self? {
return value as T
} else {
return defaultValue
}
}
}
sin embargo, la necesidad de arrojar value as T
es un hack feo. Idealmente, debería haber una manera de afirmar que T
es igual al tipo que figura en el Opcional. Tal como está, escriba los conjuntos de inferencia T
función del parámetro dado a getOrElse, y luego falla en el tiempo de ejecución si esto no coincide con el opcional y el opcional es no-nil:
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
si escribiste:
let result = optionalValue ?? 50
y optionalValue != nil
, el result
también será optional
y necesitará desenvolverlo en el futuro
Pero puedes escribir operador
infix operator ??? { associativity left precedence 140 }
func ???<T>(optLeft:T?, right:T!) -> T!
{
if let left = optLeft
{
return left
}
else { return right}
}
Ahora usted puede:
let result = optionalValue ??? 50
Y cuando optionalValue != nil
unwraped
result
será unwraped
Actualizar
Apple ahora ha agregado un operador coalescente:
var unwrappedValue = optionalValue ?? defaultValue
El operador ternario es tu amigo en este caso
var unwrappedValue = optionalValue ? optionalValue! : defaultValue
También puede proporcionar su propia extensión para la enumeración opcional:
extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}
Entonces puedes hacer:
optionalValue.or(defaultValue)
Sin embargo, recomiendo seguir al operador ternario ya que otros desarrolladores lo entenderán mucho más rápido sin tener que investigar el método or
método.
Nota : Inicié un module para agregar ayudantes comunes como esta or
en Optional
para acelerar.