Domanda

Come ha lo scopo di Opzione lavoro monade? Sto navigando il Scala api e non v'è un esempio (intendo il secondo),

  

A causa di come per le opere di comprensione, se viene restituito None dalle request.getParameter, l'intero risultato di espressione a None

Ma quando provo questo codice:

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

ottengo un errore di compilazione. Come è questo dovrebbe funzionare?

È stato utile?

Soluzione

Si ottiene un errore di compilazione a causa di questo

  name <- None

In questo modo, il tipo di None è impostato None.type e la name variabile costituirebbero dunque essere di tipo Nothing. (Cioè, sarebbe avere questo tipo se è realmente esistito, ma, ovviamente, il per la comprensione non ha nemmeno arrivare a crearlo in fase di esecuzione.) Esiste quindi nessun metodo name.trim e non verrà compilato.

Se si ha a disposizione request.getParameter("name"), il suo tipo sarebbe Option[String], name potrebbe potenzialmente avere tipo String e name.trim sarebbe la compilazione.

E 'possibile ovviare a questo specificando il tipo di None:

  name <- None: Option[String]

Altri suggerimenti

Per espandere sulla risposta di Kevin, è possibile evitare i valori wrapping Some() utilizzando l'operatore = anziché l'operatore <-:

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

Il per-di comprensione verrà compilato a qualcosa di molto simile alla versione di Kevin, ma spesso mi trovo più chiaro da usare map e filter esplicitamente evitare confusione (ad esempio i nomi delle variabili in più) che non aggiungono nulla al contenuto semantico dell'espressione.

Per espandere sulla risposta di Debilski, anche voi non c'è bisogno di avvolgere in modo esplicito i valori successivi Some(), l'unico valore che si sta effettivamente la mappatura sopra è il name originale.

Un approccio migliore sarebbe essere quello di utilizzare le operazioni map e filter direttamente invece di una per-di comprensione:

Nota: dietro le quinte, il compilatore Scala convertirà un per-la comprensione di una combinazione di carta / flatMap / filtro in ogni caso, per cui questo approccio non sarà mai meno efficiente di un per-comprensione, e può ben essere più efficiente

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

val param = None : Option[String] // request.getParameter("name")
println( clean(param).getOrElse("") )
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top