Question

comment on entend au travail Option monade? Je surfe scala api et il est un exemple (je veux dire le second),

  

En raison de la façon dont des travaux de compréhension, si None est retourné de request.getParameter, les résultats entiers d'expression dans Aucun

Mais quand j'essaie ce code:

 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(""))

je reçois une erreur de compilation. Comment est-ce censé fonctionner?

Était-ce utile?

La solution

Vous obtenez une erreur de compilation à cause de cela

  name <- None

De cette façon, le type de None est réglé sur None.type et la name variable est inférées à être de type Nothing. (C'est, il aurait ce type si elle existait réellement, mais évidemment la compréhension pour ne même pas à la création lors de l'exécution.) Par conséquent, aucune name.trim méthode existe et il ne compilera pas.

Si vous aviez request.getParameter("name") disponible, son type serait Option[String], name aurait potentiellement le type String et name.trim compilerait.

Vous pouvez contourner ce problème en spécifiant le type de None:

  name <- None: Option[String]

Autres conseils

Pour développer la réponse de Kevin, vous pouvez éviter les valeurs d'emballage dans Some() en utilisant l'opérateur de = au lieu de l'opérateur <-:

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

Le pour-comprendre compilera à quelque chose de très similaire à la version de Kevin, mais je trouve souvent plus clair d'utiliser map et filter explicitement à éviter l'encombrement (par exemple, les noms de variables supplémentaires) que rien d'ajouter au contenu sémantique de l'expression.

Pour développer la réponse de Debilski, vous pouvez aussi ne pas besoin d'envelopper explicitement les valeurs suivantes dans Some(), la seule valeur que vous êtes réellement sur la cartographie est le name d'origine.

Une meilleure approche serait d'utiliser les opérations de map et filter directement au lieu d'un pour-compréhension:

NOTE: dans les coulisses, le compilateur Scala convertira un pour-compréhension à une combinaison de carte / flatMap / filtre de toute façon, cette approche ne sera jamais moins efficace qu'un pour-compréhension, et pourrait bien être plus efficace

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

val param = None : Option[String] // request.getParameter("name")
println( clean(param).getOrElse("") )
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top