Pregunta

¿Cómo se entiende que mónada opción de trabajo? Estoy navegar por la Scala API y hay un ejemplo (me refiero a la segunda),

  

Debido a la forma de las obras de comprensión, si ninguno se volvió de request.getParameter, toda la expresión da como resultado Ninguno

Pero cuando intento este código:

 val upper = for {
   name <- None //request.getParameter("name")
   trimmed <- Some(name.trim)
   upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
 } yield upper
 println(upper.getOrElse(""))

me sale un error de compilación. ¿Cómo se supone que funciona?

¿Fue útil?

Solución

Se obtiene un error de compilación debido a esto

  name <- None

De esta manera, el tipo de None se establece en None.type y la name variable se infiere a ser de tipo Nothing. (Es decir, que tendría este tipo si en realidad existía, pero, obviamente, la de comprensión ni siquiera llegar a crear en tiempo de ejecución.) Por lo tanto no existe name.trim método y que no se compilará.

Si tuviera request.getParameter("name") disponible, su tipo sería Option[String], name tendría potencialmente tipo String y name.trim se compilará.

Se puede evitar esto especificando el tipo de None:

  name <- None: Option[String]

Otros consejos

Para ampliar la respuesta de Kevin, se puede evitar valores de envoltura en Some() usando el operador = en lugar del operador <-:

val upper = for {
   name <- None: Option[String] //request.getParameter("name")
   trimmed = name.trim
   upper = trimmed.toUpperCase if trimmed nonEmpty
} yield upper

El-comprensión de compilará a algo muy similar a la versión de Kevin, pero a menudo resultará más clara a utilizar map y filter explícitamente al desorden de evitar (por ejemplo, los nombres de variables adicionales) que no añaden nada al contenido semántico de la expresión.

Para ampliar la respuesta de Debilski, también no es necesario para envolver de manera explícita los valores subsiguientes en Some(), el único valor que realmente se aplica la relación es la más name originales.

Un mejor enfoque sería ser el uso de las operaciones map y filter directamente en lugar de una para-comprensión:

NOTA: detrás de las escenas, el compilador Scala convertirá una para la comprensión de una combinación de mapa / flatMap / filtro de todos modos, por lo que este enfoque no será menos eficiente que una para-comprensión, y puede muy bien ser más eficiente

def clean(x:Option[String]) = x map { _.trim.toUpperCase } filterNot { _.isEmpty }

val param = None : Option[String] // request.getParameter("name")
println( clean(param).getOrElse("") )
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top