Sunday, 25 December 2011

Scala block gotcha

Do you know what this line of code is going to print?
List(1,2,3).map{println("Adding 2"); _+2}

My first answer would be: 3 times "Adding 2".

Lets see:
scala> List(1,2,3).map{println("Adding 2"); _+2}
Adding 2
res11: List[Int] = List(3, 4, 5)

Hmm, it prints "Adding 2" just once...
So what is really happening here?

The cue is in understanding what is the semantics of a block in Scala.

The map function on List expects a function Int => B. The block {println("Adding 2"); _+2} is not a function Int => B. It's just a block of code which gets evaluated and returns value of the last expression. In our case when the block gets evaluated it prints "Adding 2" and then it returns a function x => x+2 (shorter _+2). Then this function is called 3 times to map elements of the list.

What is the workaround?

We just need to make sure that println is in the body of the function, that we pass to map, i.e.
scala> List(1,2,3).map{x => println("Adding 2"); x+2}
Adding 2
Adding 2
Adding 2
res12: List[Int] = List(3, 4, 5)

Enjoy!

2 comments:

  1. Thank for this tricks ! may be this snippet code explain more :

    scala> def f: Int => Int = {println("Adding 2"); _+2}
    f: Int => Int

    scala> List(1,2,3).map (f)
    Adding 2
    res9: List[Int] = List(3, 4, 5)

    ReplyDelete
  2. For the solution :


    scala> def v (x : Int) = {println("Adding 2"); x+2}
    v: (x: Int)Int

    scala> List(1,2,3).map (v)
    Adding 2
    Adding 2
    Adding 2
    res10: List[Int] = List(3, 4, 5)

    ReplyDelete