Scala 理解中的选项生成器强制其他生成器为选项?
表达式的第一个示例是基本示例。expr的第二个变量引入了一个微小的变化,我认为这会产生相同的输出。但由于编译错误而失败。原因是什么?如何修复Scala 理解中的选项生成器强制其他生成器为选项?,scala,for-comprehension,Scala,For Comprehension,表达式的第一个示例是基本示例。expr的第二个变量引入了一个微小的变化,我认为这会产生相同的输出。但由于编译错误而失败。原因是什么?如何修复 for { n <- List(1,2) c <- "ABC" } yield s"$c$n" //res0: List[String] = List(A1, B1, C1, A2, B2, C2) for { opt <- List(None, Some(1), None, None, Some(2), Non
for {
n <- List(1,2)
c <- "ABC"
} yield s"$c$n"
//res0: List[String] = List(A1, B1, C1, A2, B2, C2)
for {
opt <- List(None, Some(1), None, None, Some(2), None)
n <- opt
c <- "ABC"
} yield s"$c$n"
//Error:(14, 5) type mismatch;
//found : scala.collection.immutable.IndexedSeq[String]
//required: Option[?]
// c <- "ABC"
// ^
用于{
n回答标题问题:是的,第一个生成器为整个表达式“设置情绪”。请注意,对于像上面这样的表达式,会被分解为对flatMap
s的调用和最后一个map
(加上带过滤器的,用于警卫)
在您的情况下,第一个for表达式被分解为以下表达式:
List(1, 2).flatMap(n => "ABC".map(c => s"$c$n"))
这是因为Predef
(在每个Scala程序中隐式导入)提供了字符串
到Seq[Char]
的隐式转换
val implicitlyConverted: Seq[Char] = "ABC"
因此,它会按计划检查运行类型
现在让我们看一下表达式的第二个for是如何被去除的:
同样,我们有与上面相同的类型错误,如果我们将表达式分成几行,我们可能会更好地看到这个问题:
List(None, Some(1), None, None, Some(2), None).flatMap {
opt =>
opt.flatMap {
n =>
"ABC".map {
c =>
s"$c$n"
}
}
}
这给我们带来了以下错误:
<console>:12: error: type mismatch;
found : scala.collection.immutable.IndexedSeq[String]
required: Option[?]
"ABC".map {
^
解决这一特殊问题的更一般的方法涉及单子变压器,因为问题的根源是单子不构成;这个问题非常广泛和复杂,可能会给你一个更一般的答案。回答标题问题:是的,第一个生成器“设置情绪”对于表达式的整体。请注意,对于类似上面的表达式,将其分解为对flatMap
s的调用和最终的map
(加上用于保护的withFilter
)
在您的情况下,第一个for表达式被分解为以下表达式:
List(1, 2).flatMap(n => "ABC".map(c => s"$c$n"))
这是因为Predef
(在每个Scala程序中隐式导入)提供了字符串
到Seq[Char]
的隐式转换
val implicitlyConverted: Seq[Char] = "ABC"
因此,它会按计划检查运行类型
现在让我们看一下表达式的第二个for是如何被去除的:
同样,我们有与上面相同的类型错误,如果我们将表达式分成几行,我们可能会更好地看到这个问题:
List(None, Some(1), None, None, Some(2), None).flatMap {
opt =>
opt.flatMap {
n =>
"ABC".map {
c =>
s"$c$n"
}
}
}
这给我们带来了以下错误:
<console>:12: error: type mismatch;
found : scala.collection.immutable.IndexedSeq[String]
required: Option[?]
"ABC".map {
^
解决这一特定问题的更一般的方法涉及单子变压器,因为问题的根源是单子不构成;问题非常广泛和复杂,可能会给您一个更一般的答案。另一种“修复”方法是更改顺序:
for {
opt <- List(None, Some(1), None, None, Some(2), None)
c <- "ABC"
n <- opt
} yield s"$c$n"
//> List[String] = List(A1, B1, C1, A2, B2, C2)
用于{
opt另一种“修复”方法是更改顺序:
for {
opt <- List(None, Some(1), None, None, Some(2), None)
c <- "ABC"
n <- opt
} yield s"$c$n"
//> List[String] = List(A1, B1, C1, A2, B2, C2)
用于{
在本例中选择“是”,因为第二个提取器类似于一个flatMap
,因此您需要返回一个选项。为清楚起见,在第一种情况下,由于隐式转换,您可以在“ABC”上提取,因此该内容将成为一个列表并进行编译,在第二种情况下为“ABC”未隐式转换为选项。在本例中为“是”,因为第二个提取器类似于flatMap
,因此您需要返回一个选项。为清楚起见,在第一种情况下,由于隐式转换,您可以在“ABC”上提取,因此该内容将成为列表并进行编译,在第二种情况下为“ABC”未隐式转换为选项。答案的学术质量超出预期。非常感谢。@谢谢,我很高兴我提供了帮助!答案的学术质量超出预期。非常感谢。@谢谢,我很高兴我提供了帮助!