2

I can find a document specifying the Scala rule about coercion of functions passed to higher-order function (... the method decorator.layout is coerced automatically to a value of type Int => String).

If I defined the following.

object Foo {
  def bar[T1, R](f: T1 => R): T1 => R = f
}

def fn1(s: String): Int = 1

Then in the REPL I can do:

scala> Foo.bar({ s: String => 1 })
res: String => Int = <function1>

scala> Foo.bar(fn1)
res: String => Int = <function1>

Everything is fine and clear up to there, but if I update Foo:

object Foo {
  def bar[T1, R](f: T1 => R): T1 => R = f

  // NEW
  def bar[T1, T2, R](f: Function2[T1, T2, R]): Tuple2[T1, T2] => R = { case (c1, c2) => f(c1, c2) }
}

Then in the REPL:

scala> Foo.bar({ s: String => 1 })
res: String => Int = <function1>

scala> Foo.bar(fn1)
<console>:12: error: missing arguments for method fn1;
follow this method with `_' if you want to treat it as a partially applied function
              Foo.bar(fn1)

Some this call bar(fn1) which was working with the first version of Foo need to be updated in the following way.

scala> Foo.bar(fn1 _)
res: String => Int = <function1>

That's fine but I would like to make sure which rules the Scala compiler follows about that, when the syntax higherFn(fn) can be used and when it cannot (and that syntax higherFn(fn _) is required).

I guess the polymorphism of the higher-order function has something to do with that...

cchantep
  • 9,118
  • 3
  • 30
  • 41

1 Answers1

0

Shortly saying, higherFn(fn1) can be used when compiler knows what type is expected from fn, like T1 => R in the first case. When overloading occurs compiler should choose appropriate method first, so the expected type is unknown at the time.

P.S. IMHO, compiler could be smarter here, but it seems to be more complex to implement/describe for now.

dk14
  • 22,206
  • 4
  • 51
  • 88