我有以下for-yield循环,它接受一个布尔值,应该产生Some(string)或None,具体取决于boolean:
val theBoolean = false
val x: Option[String] =
for {
theArg <- theBoolean
} yield {
if (theArg) {
"abc"
} else {
None
}
}
Run Code Online (Sandbox Code Playgroud)
如果theBoolean它实际上是一个布尔像,这很好用false.但是,如果我想通过Option[Boolean]:
val theBoolean = Some(false)
Run Code Online (Sandbox Code Playgroud)
似乎Scala自动将Some()包装器应用于None返回 - 我得到一个抱怨"类型Option [Serializable]的表达式不符合预期类型Option [String]"(其中None是Serializable).虽然收益率与完全相同的字符串返回非常满意(它不会成为选项[Option [String]]
在这种情况下我如何返回None?
Gab*_*lla 15
for-comprehension只是一系列的语法糖flatMap,map和filter.让我们来代替您的代码:
val theBoolean = Some(false)
val x = theBoolean.map { theArg =>
if (theArg) {
"abc"
} else {
None
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,你只是映射了它的值Option,所以你要么返回Some(abc),Some(None)要么None(如果theBoolean已经None).
最低的普通型None和"abc"是java.Serializable,所以这就是为什么类型x推断的Option[Serializable],这是毫无意义的Option[Any].
可能的解决方案是
用一个 flatMap
theBoolean.flatMap(theArg => if (theArg) Some("abc") else None)
Run Code Online (Sandbox Code Playgroud)
甚至更短
theBoolean.flatMap(if (_) Some("abc") else None)
Run Code Online (Sandbox Code Playgroud)过滤和映射
theBoolean.withFilter(identity).map(_ => "abc")
Run Code Online (Sandbox Code Playgroud)我使用的地方,identity因为你正在测试价值本身.
很明显,你总是可以利用for-comprehension提供的句法糖,虽然它在这种情况下并没有真正有所作为
for {
theArg <- theBoolean
if theArg
} yield "abc"
Run Code Online (Sandbox Code Playgroud)