为什么Some(1).getOrElse(Some(1))不是Option [Int]类型?

时间:2013-07-09 20:46:28

标签: scala

我目前正在使用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)in any或者我错了吗?

有趣的

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

有效,但所有其他组合都没有......

3 个答案:

答案 0 :(得分:14)

你想:

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

由于

x.getOrElse(y)
如果x是Some(1)ySome(1)),如果x是None,或者在代码中说话,

将返回1:

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

答案 1 :(得分:7)

Option.getOrElse的类型签名是

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

这意味着当您在getOrElse上致电Option[A]时,它会尝试向您返回A类型的内容。如果默认类型(B)与A不同,则会查找距AB最近的共享祖先。在您的情况下,ABOption[Int]Int。编译器可以做的最好的事情是Any

答案 2 :(得分:1)

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

使用getOrElse,您可以将选项缩减为其包含的类型。 想象一下,它是一个解包值的过程,将其从容器中删除。

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

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

做你想做的事:

val b Option[Int] = Some(1).orElse(Some(2)) // Some(1)
相关问题