【问题标题】:Why is Some(1).getOrElse(Some(1)) not of type Option[Int]?为什么 Some(1).getOrElse(Some(1)) 不是 Option[Int] 类型?
【发布时间】:2013-07-09 20:46:28
【问题描述】:

我目前正在使用 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)

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

【问题讨论】:

    标签: scala


    【解决方案1】:

    你想要的:

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

    因为

    x.getOrElse(y)
    

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

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

    【讨论】:

    • x.orElse(Some(y)) 对于任何xy 来说总是很愚蠢。你想要x.getOrElse(y)
    • 我不是说orElse 很傻,我是说传递一个明确包裹在Some 中的值很傻。
    • @pelotom - 如果你想将它传递给需要 Option 的东西怎么办?
    • @pelotom,这正是我所做的 ;-) 评论视图模板需要一个选项 [评论]。编写的代码是这样的:找到 id 与参数 id 匹配的第一个元素(可能没有这样的元素,因此是 Option)。但是,如果它没有找到任何元素,则取而代之的是从列表中获取第一个元素(但同样,这可能是不可能的,因为列表可能是空的)。因此,最终,视图必须处理根本没有要呈现的评论的情况,因此该函数采用 Option[Review] 并且 .orElse 在我看来并不愚蠢而是天才!
    • 对于需要Option 的情况,我认为说Some(x.getOrElse(y)) 更清楚,以明确结果是全部但被提升为偏颇。但这是一个品味问题。
    【解决方案2】:

    Option.getOrElse的类型签名是

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

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

    【讨论】:

    • 不错,+1--抓住问题的核心,但没有任何具体问题的细节。
    【解决方案3】:

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

    使用getOrElse,您可以将 Option 缩减为它所包含的类型。 把它想象成一个拆包价值的过程,把它从容器中取出。

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

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

    而做你想做的是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-12-12
      • 2015-08-13
      • 2017-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多