我是 Scala 的初学者,不明白这里发生了什么:
给定:
val reverse:Option[MyObject] = ...
并且myObject.isNaire
返回 bool 值。
如果我这样做:
val v:Option[Boolean] = reverse.map(_.isNaire)
val b:Boolean = v.getOrElse(false)
它有效。
现在,如果我这样做:
val b:Boolean = reverse.map(_.isNaire).getOrElse(false)
它无法编译,类型不匹配:找到任何,必需的 bool 值
编辑:谢谢Beryllium,通过制作SSCCE,我找到了解释的开始。在第一个示例中,myObject 是一个 java 类,因此 isNaire 是一个 java.lang.Boolean。我认为隐式转换应该使这一过程变得透明,因此仍然欢迎解释。
class Test(val naire:java.lang.Boolean)
class Other {
val testValue = Some(new Test(true))
def mysteriousCompilationError:Boolean = testValue.map(_.naire).getOrElse(false)
}
注意:ScalaCompiler 是 2.10.2
最佳答案
在 scala.Predef
中,有一个从 java.lang.Boolean
到 scala.Boolean
的隐式转换:
implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue
因此,在第一种情况下,编译器会看到 java.lang.Boolean
并查找作用域中的隐式方法,将其转换为 scala.Boolean,可以方便地在 scala.Predef 中找到它。
在第二种情况下,testValue.map(_.naire).getOrElse(false)
,编译器按以下顺序执行操作:
选项[测试] => 选项[java.lang.Boolean]
getOrElse[B >: A](默认值:=> B): B
其中A
是java.lang.Boolean
且B
是Any
,因为scala.Boolean
不是>:
java.lang.Boolean
val b:Boolean
,编译器找不到从Any
到scala.Boolean
的隐式转换
解决这个问题的唯一方法是在映射操作期间告诉编译器使用从 scala.Predef
到 java.lang.Boolean
的隐式转换> 到 scala.Boolean
:
def works:Boolean = testValue.map[Boolean](_.naire).getOrElse(false)
这是一个常见问题,并且经常出现,因为 map
后跟 getOrElse
非常方便。要在没有额外类型的情况下正确修复此问题,请在选项上使用 fold
(变形):
def worksToo:Boolean = testValue.fold(false)(_.naire)
通过使用fold
,您可以获得一些额外的类型安全性,因为没有转换为常见类型。例如,您不能这样做:
def failsTypeCheck = testValue.fold("test")(_.naire)
虽然编译器对此没有问题:
def passesTypeCheck = testValue.map(_.naire).getOrElse("test")
关于Scala 推理 : fail on 1 evaluation, 成功并具有中间值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18045985/