Opción “Convertir”[x] a x en Scala
casting playframework (6)
Estoy trabajando con play para scala (2.1) y necesito convertir un valor de "Opción [Largo]" a "Largo".
Sé hacer lo contrario, quiero decir:
def toOption[Long](value: Long): Option[Long] = if (value == null) None else Some(value)
Pero en mi caso, tengo que pasar un valor de "Opción [Largo]" como un tipo a un método que toma "Largo". Cualquier ayuda por favor.
Como ya se ha mencionado, getOrElse es probablemente lo que está buscando al responder a su pregunta directamente.
Tenga en cuenta también que para convertir a una opción puede simplemente:
val myOption = Option(1)
myOption ahora será un poco (1)
val myOption = Option(null)
myOption ahora será None.
Debe decidir qué sucede cuando la opción es None
. ¿Proporcionas un valor por defecto?
def unroll(opt: Option[Long]): Long = opt getOrElse -1L // -1 if undefined
unroll(None) // -> -1
También podrías lanzar una excepción:
def unroll(opt: Option[Long]): Long = opt.getOrElse(throw
new IllegalArgumentException("The option is expected to be defined at this point")
)
unroll(None) // -> exception
En el caso, absténgase de usar null
, a menos que tenga muy buenas razones para usarlo ( opt.orNull
).
En primer lugar, su implementación de "lo contrario" tiene algunos problemas serios. Al poner un parámetro de tipo llamado Long
en el método, se está siguiendo el tipo Long
de la biblioteca estándar. Probablemente te refieres a lo siguiente:
def toOption(value: Long): Option[Long] =
if (value == null) None else Some(value)
Incluso esto no tiene sentido (ya que scala.Long
no es un tipo de referencia y nunca puede ser null
), a menos que se esté refiriendo a java.lang.Long
, que es una receta para el dolor y la confusión. Finalmente, incluso si estuviera tratando con un tipo de referencia (como String
), sería mejor que escribiera lo siguiente, que es exactamente equivalente:
def toOption(value: String): Option[String] = Option(value)
Este método devolverá None
si y solo si el value
es null
.
Para responder a su pregunta, supongamos que tenemos el siguiente método:
def foo(x: Long) = x * 2
Por lo general, no debería pensar en términos de pasar una Option[Long]
a foo
, sino de "elevar" foo
a la Option
través del map
:
scala> val x: Option[Long] = Some(100L)
x: Option[Long] = Some(100)
scala> x map foo
res14: Option[Long] = Some(200)
El punto principal de la Option
es modelar (a nivel de tipo) la posibilidad de un valor "nulo" para evitar toda una clase de problemas NullPointerException
-y. El uso del map
en la Option
permite realizar cálculos sobre el valor que puede haber en la Option
mientras continúa modelando la posibilidad de que esté vacío.
Como señala otra respuesta, también es posible usar getOrElse
para "rescatar" la Option
, pero esto generalmente no es el enfoque idiomático en Scala (excepto en los casos en que realmente hay un valor predeterminado razonable).
Este método ya está definido en la Opción [A] y se llama obtener :
scala> val x = Some(99L)
x: Some[Long] = Some(99)
scala> x.get
res0: Long = 99
El problema es que llamar a get on None lanzará una excepción NoSucheElement:
scala> None.get
java.util.NoSuchElementException: None.get
por lo tanto, no obtendrá ningún beneficio al usar un tipo de Opción.
Por lo tanto, como se indicó antes, puede usar getOrElse si puede proporcionar un valor predeterminado razonable o manejar la Excepción.
La forma idiomática de la escala sería utilizar un mapa o una comprensión.
x map (_ + 1)
res2: Option[Long] = Some(100)
o
for (i <- x) yield i +1
res3: Option[Long] = Some(100)
La opción es una forma de localizar efectos secundarios (su función puede devolver un valor vacío). Y buen estilo para elevar su cálculo a Opción (la opción es Mónada con métodos de mapa y mapa plano ).
val x = Option[Long](10)
x.map { a => a + 10 }
Y extraer el valor con el procesamiento manual del efecto secundario:
val res = x match {
case Some(a) => s"Value: $a"
case None => "no value"
}
Si tienes x como opción [Long], x.get
te dará Long.