我遇到编译错误:
Error:(64, 9) type mismatch;
found : Array[(String, String)]
required: Option[?]
y <- x
^
在一个片段中:
val z = Some(Array("a"->"b", "c" -> "d"))
val l = for(
x <- z;
y <- x
) yield y
为什么Array上的生成器不生成该数组的项?需求从何而来呢?
更荒谬的是,如果我用println(y)替换“ yield”,那么它将编译。
Scala版本:2.10.6
这是因为for
表达式被转换为map
,flatmap
和foreach
表达式的方式。让我们首先简化您的示例:
val someArray: Some[Array[Int]] = Some(Array(1, 2, 3))
val l = for {
array: Array[Int] <- someArray
number: Int <- array
} yield number
根据Scala language specification的相关部分,首先将其翻译为
someArray.flatMap {case array => for (number <- array) yield number}
依次翻译为
someArray.flatMap {case array => array.map{case number => number}}
问题是someArray.flatMap需要一个从Array[Int]
到Option[Array[Int]]
的函数,而我们提供了一个从Array[Int]
到Array[Int]
的函数。
如果将yield number
替换为println(number)
,则编译错误消失的原因是,对于for循环而言,翻译的理解与对于for循环的理解不同:现在将其翻译为someArray.foreach{case array => array.foreach {case item => println(item)}}
,这没有相同的键入问题。
一种可能的解决方案是将Option转换为您想要最终获得的集合的类型,以便其flatMap方法将具有正确的签名:
val l = for {
array: Array[Int] <- someArray.toArray
number: Int <- array
} yield number
这是通常的“选项必须转换为混合单声道”。
scala> for (x <- Option.option2Iterable(Some(List(1,2,3))); y <- x) yield y
res0: Iterable[Int] = List(1, 2, 3)
比较
scala> for (x <- Some(List(1,2,3)); y <- x) yield y
<console>:12: error: type mismatch;
found : List[Int]
required: Option[?]
for (x <- Some(List(1,2,3)); y <- x) yield y
^
到
scala> Some(List(1,2,3)) flatMap (is => is map (i => i))
<console>:12: error: type mismatch;
found : List[Int]
required: Option[?]
Some(List(1,2,3)) flatMap (is => is map (i => i))
^
或
scala> for (x <- Some(List(1,2,3)).toSeq; y <- x) yield y
res3: Seq[Int] = List(1, 2, 3)