8

我目前正在使用 Scala 开展一个项目,似乎我并不完全了解 Scala 的类型系统:-/

我有以下情况:

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

不幸的是,编译器说,他无法将 Product 转换为 Option[Review],所以我更改了代码

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

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

这似乎现在可以工作,即使它与它不完全相同,例如,如果提交了无效的评论 ID,则不再显示第一条记录。然后它会假装还没有可用的评论。

然后我将问题分解为一个非常简单的示例:

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

那么,有谁知道,为什么右侧的表达式不是 Option[Int] 类型的?Some(1) 和 None 都直接从 Option 继承,这个表达式实际上是 Some(1) 或者我错了吗?

有趣的是

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

有效,但所有其他组合不...

4

3 回答 3

14

你自找的:

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

因为

x.getOrElse(y)

如果 x 是,将返回 1Some(1)y(which is Some(1)) 如果 x 是None,或者用代码说话:

if (Some(1).isDefined) 1 else Some(1)
于 2013-07-09T20:50:08.613 回答
9

的类型签名Option.getOrElse

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

这意味着当你调用getOrElsean时Option[A],它会尝试返回一些类型的东西A。如果 default ( B) 的类型与 不同A,它将寻找Aand的最近的共享祖先B。在你的情况下,A并且BOption[Int]Int。编译器能做的最好的事情是Any.

于 2013-07-09T21:51:21.017 回答
1

一个 Option 值有两种表示,一个好值 ( Some(...)) 或一个坏值 ( None)。

您可以将getOrElseOption 减少到它包含的类型。把它想象成一个拆包价值的过程,把它从容器中取出。

在这个解包过程中,Option被剥离并且只返回它包含的类型,所以在你的例子中你真的有这个:

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

做你想做的是:

val b Option[Int] = Some(1).orElse(Some(2)) // Some(1)
于 2013-07-09T21:04:56.193 回答