2013-07-09 17 views
6

Obecnie pracuję nad projektem z Scala i wydaje się, że nie w pełni zrozumieć Scala system typów: -/Dlaczego niektóre (1) .getOrElse (niektóre (1)) nie typu Opcja [Int]?

Mam następującą sytuację:

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

Niestety kompilator mówi, że nie można przekonwertować Produkt na wariancie [recenzja], więc zmieniłem kod

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

z

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

, które wydaje się teraz działać, nawet jeśli nie jest to dokładnie to samo, co na przykład, nie pokazuje już pierwszego rekordu, jeśli przesłano nieprawidłowy identyfikator opinii. następnie będzie udawać, że nie ma jeszcze dostępnych opinii.

I wtedy wybuchła problemu w dół do baaardzo prosty próbki:

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

Więc ma ktoś jakiś pomysł, dlaczego wyrażenie po prawej stronie nie ma opcji typu [Int] ?? Zarówno niektóre (1) i Brak dziedziczą bezpośrednio z Opcji i to wyrażenie jest w rzeczywistości Niektóre (1) w ogóle, czy też jestem w błędzie?

wystarczająco Interestinly

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

prace, ale wszystkie inne kombinacje nie ...

Odpowiedz

13

Chciałeś:

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

Ponieważ

x.getOrElse(y) 

zwróci 1 jeżeli x to Some(1) lub y (co jest Some(1)) jeśli x jest None, lub mówiąc w kodzie:

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

'x.orElse (Some (y))' jest zawsze głupie dla dowolnego 'x' i' y'. Chcesz 'x.getOrElse (y)'. –

+2

@pelotom to po prostu [nie jest prawdą] (http://stackoverflow.com/q/14305308/298389) –

+0

Nie mówię, że 'orElse' jest głupie, mówię, że przekazanie mu wartości jawnie zapakowane w' ' Niektóre są głupie. –

1

wartość opcja ma dwie reprezentacje, dobra jakość (Some(...)) lub złą jakość (None).

Z getOrElse można zmniejszyć opcję do typu zawartego przez niego. Wyobraź sobie, że to proces rozpakowywania wartości, usuwania jej z pojemnika.

W tym procesie rozpakowaniu Option jest usuwany i zwracana jest tylko rodzaj zawartej przez niego więc w przykładzie naprawdę masz to:

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

I robić to, co chcesz:

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

typu podpis Option.getOrElse jest

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

Oznacza to, że po wywołaniu getOrElse na Option[A], spróbuje on zwrócić coś typu A. Jeśli typ wartości domyślnej (B) nie jest taki sam jak A, będzie on szukał najbliższego wspólnego przodka A i B. W twoim przypadku A i BOption[Int] i Int. Najlepszym kompilatorem jest Any.

+0

nice one, + 1 - trafia do sedna sprawy, ale bez żadnych szczegółów specyficznych dla problemu. – doug

Powiązane problemy