2013-11-04 10 views
13

Io lavoro con play per scala (2.1) e ho bisogno di convertire un valore "Opzione [Lungo]" in "Lungo".Opzione "Converti" da [x] a x in Scala

io so come fare il contrario, voglio dire:

def toOption[Long](value: Long): Option[Long] = if (value == null) None else Some(value) 

Ma nel mio caso, devo passare un valore di "Option [Lungo]" come un tipo in un metodo che prende "Long ". Qualsiasi aiuto per favore.

risposta

22

Prima di tutto, l'implementazione del "contrario" ha alcuni problemi seri. Inserendo un parametro di tipo Long nel metodo, si nasconde il tipo Long dalla libreria standard. Probabilmente hanno il seguente significato invece:

def toOption(value: Long): Option[Long] = 
    if (value == null) None else Some(value) 

Anche questo è una specie di assurdo (dal scala.Long non è un tipo di riferimento e non può mai essere null), a meno che non ti riferisci a java.lang.Long, che è una ricetta per il dolore e la confusione. Infine, anche se si trattasse di un tipo di riferimento (come String), si sarebbe meglio scrivere il seguente, che è esattamente equivalente:

def toOption(value: String): Option[String] = Option(value) 

Questo metodo restituirà None se e solo se è valuenull .

Per rispondere alla sua domanda, supponiamo di avere il seguente metodo:

def foo(x: Long) = x * 2 

Non si dovrebbe generalmente pensare in termini di superamento di un Option[Long] a foo, ma piuttosto di "lifting" foo nella Option via map :

scala> val x: Option[Long] = Some(100L) 
x: Option[Long] = Some(100) 

scala> x map foo 
res14: Option[Long] = Some(200) 

il punto di Option è per modellare (a livello di tipo) la possibilità di un valore "nullo" al fine di evitare un intero classe di NullPointerException -y problemi. L'utilizzo di map su Option consente di eseguire calcoli sul valore che può essere nel Option continuando a modellare la possibilità che sia vuoto.

come un'altra nota di risposta, è anche possibile utilizzare getOrElse a "bail out" del Option, ma questo di solito non è l'approccio idiomatico a Scala (tranne nei casi in cui non v'è davvero un valore predefinito ragionevole).

1

È necessario decidere cosa succede quando l'opzione è None. Fornisci un valore predefinito?

def unroll(opt: Option[Long]): Long = opt getOrElse -1L // -1 if undefined 

unroll(None) // -> -1 

Si potrebbe anche un'eccezione:

def unroll(opt: Option[Long]): Long = opt.getOrElse(throw 
    new IllegalArgumentException("The option is expected to be defined at this point") 
) 

unroll(None) // -> exception 

Nel caso in cui, non utilizzare null, a meno che non si dispone di ottimi motivi per usarlo (opt.orNull).

2

L'opzione è un modo per localizzare l'effetto collaterale (la funzione può restituire un valore vuoto).E buon stile di sollevare il calcolo di opzione (Opzione è Monad con mappa & flatMap metodi).

val x = Option[Long](10) 
x.map { a => a + 10 } 

E estrarre valore con l'elaborazione manuale di effetto collaterale:

val res = x match { 
    case Some(a) => s"Value: $a" 
    case None => "no value" 
} 
+2

+1 per l'utilizzo della corrispondenza del modello per estrarre i valori facoltativi. –

5

Questo metodo è già stato definito su Option [A] e si chiama ottenere:

scala> val x = Some(99L) 
x: Some[Long] = Some(99) 

scala> x.get 
res0: Long = 99 

Il problema è che chiamare su Nessuno getterà un'eccezione NoSucheElement:

scala> None.get 
java.util.NoSuchElementException: None.get 

pertanto non si otterranno benefici dall'utilizzo di un tipo di Opzione.

Pertanto, come indicato in precedenza, è possibile utilizzare getOrElse se è possibile fornire un valore predefinito ragionevole o gestire l'eccezione.

Il modo scala idiomatica sarebbe utilizzando mappa o un per-comprensione

x map (_ + 1) 
res2: Option[Long] = Some(100) 

o

for (i <- x) yield i +1 
res3: Option[Long] = Some(100) 
+1

Questo è esattamente quello che sto cercando. Grazie Andreas. – Nandakishore

0

Come già accennato getOrElse è probabilmente quello che stai cercando nel rispondere alla tua domanda direttamente.

Si prega di notare, inoltre, che per convertire a un'opzione si può semplicemente:

val myOption = Option(1) 

myoption sarà ora Alcuni (1)

val myOption = Option(null) 

myoption sarà ora None.

28

Se si dispone di x come Opzione [Lungo], x.get ti darà Long.

+3

Questa risposta è sbagliata. Se x è 'None' (che è un possibile valore di' Option [Long] '), chiamare' get' genererà un errore. –

+5

Possiamo usare x.getOrElse (Nessuno) – user3886907

+1

Risposta semplice, senza senso. –