David Portabella David Portabella - 1 month ago 16
Scala Question

Scala, different behaviour when calling `map(f)` vs `map(v => f(v))`

I get a different behaviour when calling

map(f)
vs
map(v => f(v))
. Why?

libraryDependencies += "com.lihaoyi" %% "pprint" % "0.4.1"

case class Entry(id: Int, text: String)
val entry = Entry(1, "hello")

def toPrettyString[T](o: T)(implicit pp: pprint.PPrint[T]) =
pprint.tokenize(o)(pp).mkString

println(toPrettyString(entry)) // I get Entry(1, "hello"), as expected

List(entry).map(toPrettyString).foreach(println) // I get Entry(1,hello), not what I want
List(entry).map(e => toPrettyString(e)).foreach(println) // I get Entry(1, "hello"), as expected

Answer

Eta-expansion (which turns the method toPrettyString used as a value into an anonymous function) happens before type parameter inference, you can think of it as equivalent to

def toPrettyString1[T]: T => String = 
  (x: T) => toPrettyString(x)

List(entry).map(toPrettyString1)

in toPrettyString1, the default implicit instance of PPrint, which just calls toString, has to be chosen.

In List(entry).map(e => toPrettyString(e)), type of e is inferred to be Entry and so the macro generates the correct implicit.

https://issues.scala-lang.org/browse/SI-7641

Comments