9

When I call

System.err.println("Before")
System.err.flush()
val foo: Map[Int, T] = t mapValues (fn(_))
System.err.println(foo.head) //prevent optimiser from delaying the construction of 'foo' 
System.err.println("After")
System.err.flush()

with fn having a debug print statement inside, I get this output:

Before
...head item...
After
...debug print statement from fn...
...debug print statement from fn...

I don't understand why the debug print statements are being called after "After" is printed, and I don't understand why I'm getting it twice --- unless mapValues creates a lazy map?

2 Answers 2

14

Yes it is. It maps to an intermediate class that holds fn and doesn't evaluate until access (again and again).

def mapValues[W](f: V => W): Map[K, W] = new MappedValues(f)

Use a strict map if you don't want lazy evaluation. That is:

collection map { case (k, v) => (k, fn(v)) }
Sign up to request clarification or add additional context in comments.

1 Comment

Crucial feature is that you don't need to rehash map after mapValues, because keys didn't change. With map from you example, compiler cannot give guarantees.
8

Keep in mind that the MappedValues implementation evaluates the function on every access -- different from a Scala lazy val that evaluates only once. You might be seeing the output twice when stepping through the code. Expanding the val foo in the debugger window will iterate over the values, calling function fn and generating debug output.

If you provide code for map t and function fn, then we might be able to help.

1 Comment

It's fine – it was mainly that (as always) unexpected behaviour was troubling and needed to be tracked down, rather than causing a concrete problem. But thank you for the offer of help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.