Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

For comprehension over Option array

I am getting compilation error:

Error:(64, 9) type mismatch;
 found   : Array[(String, String)]
 required: Option[?]
      y <- x
        ^

in a fragment:

val z = Some(Array("a"->"b", "c" -> "d"))
val l = for(
  x <- z;
  y <- x
) yield y

Why generator over Array does not produce items of the array? And where from requirement to have Option is coming from?

To be more ridiculous, if I replace "yield" with println(y) then it does compile.

Scala version: 2.10.6

like image 559
Vadym Chekan Avatar asked Dec 02 '25 20:12

Vadym Chekan


1 Answers

This is because of the way for expressions are translated into map, flatmap and foreach expressions. Let's first simplify your example:

val someArray: Some[Array[Int]] = Some(Array(1, 2, 3))
val l = for {
  array: Array[Int] <- someArray
  number: Int <- array
} yield number

In accordance with the relevant part of the Scala language specification, this first gets translated into

someArray.flatMap {case array => for (number <- array) yield number}

which in turn gets translated into

someArray.flatMap {case array => array.map{case number => number}}

The problem is that someArray.flatMap expects a function from Array[Int] to Option[Array[Int]], whereas we've provided a function from Array[Int] to Array[Int].

The reason the compilation error goes away if yield number is replaced by println(number) is that for loops are translated differently from for comprehensions: it will now be translated as someArray.foreach{case array => array.foreach {case item => println(item)}}, which doesn't have the same typing issues.

A possible solution is to begin by converting the Option to the kind of collection you want to end up with, so that its flatMap method will have the right signature:

val l = for {
  array: Array[Int] <- someArray.toArray
  number: Int <- array
} yield number
like image 152
Ben Avatar answered Dec 05 '25 03:12

Ben



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!