我目前正在使用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)
有效,但所有其他组合都没有......
答案 0 :(得分:14)
你想:
val a: Option[Int] = Some(1).orElse(Some(1))
由于
x.getOrElse(y)
如果x是Some(1)
或y
(Some(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
不同,则会查找距A
和B
最近的共享祖先。在您的情况下,A
和B
为Option[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)