1

Consider the following Scala code.

object Q{
  trait C{
    def f(x: Int) : Int
  }

  def applyTo3(c: C) = c.f(3)

  def main(args: Array[String]) = println(applyTo3(x => x+1))
}

This looks like it shouldn't compile: the function applyTo3 expects an argument of type C, but instead is given an argument of type Int => Int. But in fact it does compile, and gives the result 4 when run. The function is somehow being converted to an object of type C, but I don't see how.

Gavin

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
Gavin Lowe
  • 121
  • 1
  • 4
  • 5
    Because Scala 2.12 onwards... the `Function1[A, B]` or `A => B` is a valid expression for Java SAM interfaces. https://www.scala-lang.org/news/2.12.0/#lambda-syntax-for-sam-types – sarveshseri Feb 24 '23 at 16:01
  • https://stackoverflow.com/questions/22820352/scala-single-method-interface-implementation – Dmytro Mitin Feb 24 '23 at 16:12
  • Opinion: I think this answer is actually a very nice candidate for a minimalistic canonical question about `[single-abstract-method]` in `[scala]`. I'd rather prefer that this one is answered, and some others are closed as duplicates. – Andrey Tyukin Feb 24 '23 at 16:38

2 Answers2

0

good question, I believe it happens due to a concept called Functional Interface, which is when it comes to an interface with a single method, the implementation of such an interface is accepted as a higher order function.

-1

As mentioned in the comments, this is lambda syntax for SAM (Single Abstract Method).

If we break out the argument to your function, we can see what this syntactic sugar does for us (I have also added a return type for applyTo3):

object Q{
  trait C{ .. }

  def applyTo3(c: C): Int = ..

  // Syntactic sugar
  val arg: C = x => x + 1 // We have an implementation of our single abstract method (f), wrapped in an instance of C

  // We could also write this as (a lot more boilerplate):
  val standardArg: C = new C {
    override def f(x: Int): Int = x + 1
  }

  def main(args: Array[String]) = println(applyTo3(arg)) // provide our instance of C (arg) to `applyTo3`
}

Here is more information on the language specifications for SAM conversion requirements: https://www.scala-lang.org/files/archive/spec/2.12/06-expressions.html#sam-conversion

  • 1
    It's not me who downvoted but lambdas are not syntactic sugar for anonymous inner classes. Actually they can compile to different bytecode. Lambdas to invokedynamic while inner classes to invokeinterface. – Dmytro Mitin Mar 02 '23 at 03:33