为了理解 Option 数组
For comprehension over Option array
我遇到编译错误:
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
为什么数组生成器不生成数组项? Option 的要求来自哪里?
更荒谬的是,如果我用 println(y) 替换 "yield" 那么它确实可以编译。
Scala 版本:2.10.6
这是通常的 "option must be converted to mix monads" 事情。
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)
这是因为 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 comprehensions 的翻译不同:它现在将被翻译为 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
我遇到编译错误:
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
为什么数组生成器不生成数组项? Option 的要求来自哪里?
更荒谬的是,如果我用 println(y) 替换 "yield" 那么它确实可以编译。
Scala 版本:2.10.6
这是通常的 "option must be converted to mix monads" 事情。
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)
这是因为 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 comprehensions 的翻译不同:它现在将被翻译为 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