Tengo curiosidad:¿Por qué algunos (null) no se consideran ninguno?
scala> Some(null) == None
res10: Boolean = false
¿Por qué no se Some(null)
transformaron a None
?
Tengo curiosidad:¿Por qué algunos (null) no se consideran ninguno?
scala> Some(null) == None
res10: Boolean = false
¿Por qué no se Some(null)
transformaron a None
?
Debe usar Option(null)
para alcanzar el efecto deseado y devolver None
.
Some(null)
simplemente crea un nuevo Option
con un valor definido (de ahí Some
), que es en realidad null
, y hay pocas razones válidas para crear nunca uno como éste en el código real.
Desafortunadamente, null
es un valor válido para cualquier tipo de AnyRef
, una consecuencia de la interoperabilidad de Scala con Java. Entonces, un método que toma un objeto de tipo A
y, internamente, lo almacena dentro de un Option
, bien podría necesitar almacenar un null
dentro de esa opción.
Por ejemplo, supongamos que tiene un método que toma el encabezado de una lista, comprueba si esa cabecera corresponde a una clave en una tienda, y luego devuelve verdadero si lo es. Se podría aplicar de esta manera:
def isFirstAcceptable(list: List[String], keys: Set[String]): Boolean =
list.headOption map keys getOrElse false
lo tanto, aquí está la cosa ... si el que en el interior list
keys
y venir de alguna API de Java, que tanto bien puede contener null
! Si Some(null)
no fue posible, entonces isFirstAcceptable(List[String](null), Set[String](null))
devolvería false
en lugar de true
.
+1 Bonito caso de uso de por qué 'Some (null)' debería existir! –
Como un simple experimento mental, considere dos listas de cadenas, una de longitud 5 y uno de longitud 20.
Debido a que estamos ejecuta en la JVM, es posible insertar null
como un elemento válido en uno de estas listas, así que colóquelo en la lista larga como elemento # 10
¿Cuál es, entonces, la diferencia entre los valores devueltos por las dos expresiones siguientes?
EDIT: intercambiada get
para lift
, yo estaba pensando en los mapas ...
shortList.lift(10) //this element doesn't exist
longList.lift(10) //this element exists, and contains null
Gran parte de WTFs de Scala se puede atribuir a su necesidad de compatibilidad con Java. null
se usa a menudo en Java como un valor, lo que indica, tal vez la ausencia de un valor. Por ejemplo, hashMap.get(key)
devolverá null
si la clave no coincide.
Con esto en mente, considere los siguientes valores posibles de envolver un método devolviendo un valor nulo en un Option
:
if (b) Some(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked;
Some(value) // the method was invoked and a value returned; or
Some(null) // the method was invoked and null was returned.
Some(null)
parece suficientemente distinta de None
en este caso, para justificar lo que permite que en el lenguaje.
Por supuesto, si esto no es deseable en su caso, entonces simplemente uso:
if (b) Option(hashMap.get(key)) else None
// becomes -->
None // the method was not invoked or the mapped value was null; or
Some(value) // the method was invoked and a value returned
Creo que los otros en el hilo hacen un buen trabajo explicando por qué Some(null)
"debe" existir, pero si le toca estar Some(null)
conseguir algún lugar y quieren una forma rápida para convertirlo en None
, he hecho esto antes:
scala> val x: Option[String] = Some(null)
x: Option[String] = Some(null)
scala> x.flatMap(Option(_))
res8: Option[String] = None
y cuando el Option
de partida es un valor no nulo de fiar cosas funcionan como es probable que desee:
scala> val y: Option[String] = Some("asdf")
y: Option[String] = Some(asdf)
scala> y.flatMap(Option(_))
res9: Option[String] = Some(asdf)
De hecho, el "por qué" es interesante, pero la mayoría de nosotros probablemente se parezca más a "qué hacer a continuación". Muchas gracias. – fanfabbb
Debido opción se considera para ser una Functor y ser un Functor significa:
unit
función (apply
o simplemente Option("blah")
en Scala)map
función que transforma el valor de T=>B
pero no es un contextoEn este tema, la parte principal es # 2 - Option(1).map(t=>null)
no puede transformar el contexto. Some
debe permanecer. ¡De lo contrario, frena la ley asociativa!
basta con considerar las siguientes leyes ejemplo:
def identity[T](v: T) = v
def f1(v: String) = v.toUpperCase
def f2(v: String) = v + v
def fNull(v: String): String = null
val opt = Option("hello")
//identity law
opt.map(identity) == opt //Some(hello) == Some(hello)
//associative law
opt.map(f1 _ andThen f2) == opt.map(f1).map(f2) //Some(HELLOHELLO) == Some(HELLOHELLO)
opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) == Some(nullnull)
Pero lo que si Option("hello").map(t=>null)
producido None
? ley asociativa se rompería:
opt.map(fNull _ andThen f2) == opt.map(fNull).map(f2) //Some(nullnull) != None
Ese es mi pensamiento, que puede estar mal
Esto no explica mucho ... ¿Podría ser más explícito? –
@Mauricio Daniel tiene un buen ejemplo de por qué 'Some (null)' no debe transformarse en 'None'. –