Reputation: 1493
I am currently working on a project with Scala and it seems I don't fully understand Scala's Typesystem :-/
I have the following situation:
def reviews(id: Int) = Action { implicit request =>
Ok(html.products.reviews(
reviewlist,
reviewlist
.find(review => review.id == id)
.getOrElse(reviewlist.headOption)
))
}
Unfortunately the compiler says, he cannot convert Product to Option[Review], so I changed the code
reviewlist
.find(review => review.id == id)
.getOrElse(reviewlist.headOption)
with
id match {
case 0 => reviewlist.headOption
case id => reviewlist.find(review => review.id == id)
}
which seems to work now, even though its not exactly the same thing as it does, for example, not show the first record anymore if an invalid review id is being submitted. it will then pretend, that there are no reviews available yet.
I then broke the problem down to a veeery simple sample:
val a: Option[Int] = Some(1).getOrElse(Some(1))
So, has anyone an idea, why the expression on the right side is not of the type Option[Int]?? Both, Some(1) and None inherit directly from Option and this expression is actually Some(1) in any or am I wrong?
Interestinly enough
val a: Option[Int] = None.getOrElse(None)
works, but all other combinations do not...
Upvotes: 8
Views: 6034
Reputation: 57609
An Option value has two representations, a good value (Some(...)
) or a bad value (None
).
With getOrElse
you can reduce an Option to the type contained by it.
Imagine it as being a process of unpacking the value, removing it from the container.
In this process of unpacking, the Option
is stripped and only the type contained by it is returned,
so in your example you really have this:
val a int = Some(1).getOrElse(2) // 1
And to do what you want is:
val b Option[Int] = Some(1).orElse(Some(2)) // Some(1)
Upvotes: 1
Reputation: 675
The type signature of Option.getOrElse
is
getOrElse[B >: A](default: ⇒ B): B
That means that when you call getOrElse
on an Option[A]
, it is going to try to return you something of type A
. If the type of default (B
) isn't the same as A
, it is going to look for the closest shared ancestor of A
and B
. In your case, A
and B
are Option[Int]
and Int
. The best the compiler can do is Any
.
Upvotes: 9
Reputation: 62835
You wanted:
val a: Option[Int] = Some(1).orElse(Some(1))
Because
x.getOrElse(y)
will return 1 if x is Some(1)
or y
(which is Some(1)
) if x is None
, or speaking in code:
if (Some(1).isDefined) 1 else Some(1)
Upvotes: 14