¿Proporcionando un valor predeterminado para un Opcional en Swift?

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?

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 módulo para agregar ayudantes comunes como esta or en Optional para acelerar.

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" 

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 ???(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

Lo siguiente parece funcionar

 extension Optional { func getOrElse(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 

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 este repository.