0

Below code is multipling the elements of each inner Array and returning these elements as an Array :

object tupletest {
  println("Welcome to the Scala worksheet")       //> Welcome to the Scala worksheet

  val data = Array(("a", Array((1.0, 2.0))), ("b", Array((3.0, 4.0))))
                                                  //> data  : Array[(String, Array[(Double, Double)])] = Array((a,Array((1.0,2.0))
                                                  //| ), (b,Array((3.0,4.0))))

  for {

    (s, tuples) <- data

    sum1 = tuples.map(_._1).sum
    sum2 = tuples.map(_._2).sum

  } yield sum1 * sum2                             //> res0: Array[Double] = Array(2.0, 12.0)

Reading the explanation of for comprehensions at http://www.scala-lang.org/old/node/111 I still don't understand how above code is evaluated ?

Is this for comprehension similar to nested for loops ?

If I attempt to access the second element of the Array then java.lang.ArrayIndexOutOfBoundsException is thrown :

for {

    (s, tuples) <- data

    sum1 = tuples(1)

  } yield tuples                                  //> java.lang.ArrayIndexOutOfBoundsException: 1

But this should not occur, since each array is of size 2 ?

Update :

Why use :

for {

    (s, tuples) <- data

    sum1 = tuples.map(_._1).sum
    sum2 = tuples.map(_._2).sum

  } yield sum1 * sum2                             //> res0: Array[Double] = Array(2.0, 12.0)

instead of :

  data.map { case (s, tuples) =>

    val sum1 = tuples.map(_._1).sum
    val sum2 = tuples.map(_._2).sum

    sum1 * sum2
    }  

Is using map function not clearer ?

This question/answer also helped in explaining this :

Confused with the for-comprehension to flatMap/Map transformation

Community
  • 1
  • 1
blue-sky
  • 51,962
  • 152
  • 427
  • 752

1 Answers1

1

tuples refers to Array((1.0, 2.0)) and Array((3.0, 4.0)), which both contain only one element. Therefore, tuples(1) is an out of bounds error.

The code is equivalent to the following:

data.map { case (s, tuples) =>
    val sum1 = tuples(1)
    tuples
}

Whether you use for comprehension or map is personal choice. for is mostly useful when you'd otherwise have a chain of flatMaps followed by a map, or when you expect a pattern match to fail and want to ignore it.

  • thanks, please see question update. Is there a rule which describes the transformation of a for comprehension to a map function ? Is this related to "Scala substitution model" ? – blue-sky Jul 24 '14 at 10:42