2013-07-09 12 views
6

Attualmente sto lavorando su un progetto con Scala e sembra non comprendere appieno sistema dei tipi di Scala: -/Perché alcuni (1) .getOrElse (alcuni (1)) non sono di tipo Opzione [Int]?

ho la seguente situazione:

def reviews(id: Int) = Action { implicit request => 
    Ok(html.products.reviews(
    reviewlist, 
    reviewlist 
     .find(review => review.id == id) 
     .getOrElse(reviewlist.headOption) 
)) 
} 

Purtroppo il compilatore dice, non può convertire prodotto Opzione [Review], così ho cambiato il codice

reviewlist 
    .find(review => review.id == id) 
    .getOrElse(reviewlist.headOption) 

con

id match { 
    case 0 => reviewlist.headOption 
    case id => reviewlist.find(review => review.id == id) 
} 

che sembra funzionare ora, anche se non è esattamente la stessa cosa che fa, per esempio, non mostrare più il primo record se viene inviato un ID di recensione non valido. farà quindi finta che non ci siano ancora recensioni disponibili.

Poi ho rotto il problema a un campione mooolto semplice:

val a: Option[Int] = Some(1).getOrElse(Some(1)) 

Così, qualcuno ha un'idea, perché l'espressione sul lato destro, non è del tipo opzione [Int] ?? Entrambi, Some (1) e None ereditano direttamente da Option e questa espressione è in realtà Some (1) in any o I I wrong?

abbastanza Interestinly

val a: Option[Int] = None.getOrElse(None) 

opere, ma tutte le altre combinazioni non lo fanno ...

risposta

13

Volevi:

val a: Option[Int] = Some(1).orElse(Some(1)) 

Perché

x.getOrElse(y) 

restituirà 1 se x è Some(1) o y (che è Some(1)) se x è None, o parlare in codice:

if (Some(1).isDefined) 1 else Some(1) 
+1

'x.orElse (Some (y))' è sempre sciocco per qualsiasi 'x' e' y'. Vuoi 'x.getOrElse (y)'. –

+2

@pelotom è semplicemente [non vero] (http://stackoverflow.com/q/14305308/298389) –

+0

Non sto dicendo che 'orElse' è sciocco, sto dicendo che passandogli un valore esplicitamente racchiuso in' Alcuni sono sciocchi. –

1

valore un'opzione ha due rappresentazioni, un buon valore (Some(...)) o un cattivo valore (None).

Con getOrElse è possibile ridurre un'opzione al tipo in essa contenuto. Immagina che si tratti di un processo di decompressione del valore, rimuovendolo dal contenitore.

In questo processo di apertura della confezione l'Option è spogliato e solo viene restituito il tipo di contenuto da esso, così nel tuo esempio hai davvero questo:

val a int = Some(1).getOrElse(2) // 1 

E per fare ciò che si vuole è:

val b Option[Int] = Some(1).orElse(Some(2)) // Some(1) 
6

La firma tipo di Option.getOrElse è

getOrElse[B >: A](default: ⇒ B): B 

Ciò significa che quando si chiama getOrElse su un Option[A], si tenterà di restituire qualcosa di tipo A. Se il tipo di valore predefinito (B) non è lo stesso di A, cercherà il più vicino antenato condiviso di A e B. Nel tuo caso, A e B sono Option[Int] e Int. Il meglio che il compilatore può fare è Any.

+0

nice one, + 1 - arriva al nocciolo della questione ma senza dettagli specifici del problema. – doug

Problemi correlati