我收到编译错误:
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
为什么generator over Array不会产生数组项?从需求中选择的来源是什么?
更荒谬的是,如果我用println(y)替换“yield”,那么它就会编译。
Scala版本:2.10.6
答案 0 :(得分:2)
这是通常的“选项必须转换为混合monad”的事情。
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)
答案 1 :(得分:2)
这是因为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需要一个从Option[Array[Int]]
到Option[Array[Int]]
的函数,而我们提供的函数从Array[Int]
到Array[Int]
。
如果yield number
被println(number)
替换,则编译错误消失的原因是for循环的翻译方式与理解不同:它现在将被翻译为someArray.foreach{case array => array.foreach {case item => println(item)}}
,而不是&# 39; t有相同的打字问题。
一种可能的解决方案是首先将Option转换为您想要最终使用的集合类型,以便其flatMap方法具有正确的签名:
val l = for {
array: Array[Int] <- someArray.toArray
number: Int <- array
} yield number