对于选项数组的理解

问题描述 投票:3回答:2

我遇到编译错误:

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

arrays scala optional for-comprehension
2个回答
3
投票

这是因为for表达式被转换为mapflatmapforeach表达式的方式。让我们首先简化您的示例:

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

2
投票

这是通常的“选项必须转换为混合单声道”。

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)
© www.soinside.com 2019 - 2024. All rights reserved.