vsnyc vsnyc - 9 months ago 49
Scala Question

What does "double right-arrow Type" with no LHS mean in function argument

I am having trouble interpreting "double-rightarrow Type" specified as a function argument without a LHS (left hand side) e.g.

() => Int
is from
but what does just
=> Int
e.g. see the first argument of
method below, what is the type of
? Is it
(Int, () => Int) => Int

For the definition of
, where y is passed by name, I've interpreted it as a function with no argument that will produce an Int, which looks equivalent to definition of

I could try to reason that
takes the second argument as call by name, and is not from
() => Int
but that is contradicting that fact that
definitions are identical in javap. What am I missing?

object ParamTest {
def foo(f: (Int, => Int) => Int, x: Int) : Int = 10
def bar(x: Int, y: => Int) : Int = 20
def baz(x: Int, f: () => Int) : Int = 30
def qux(f: (Int, () => Int) => Int, x: Int) : Int = 40

For testing I compiled the above class with
scalac ParamTest.scala

javap ParamTest
gives me:

public final class ParamTest {
public static int qux(scala.Function2<java.lang.Object, scala.Function0<java.lang.Object>, java.lang.Object>, int);
public static int baz(int, scala.Function0<java.lang.Object>);
public static int bar(int, scala.Function0<java.lang.Object>);
public static int foo(scala.Function2<java.lang.Object, scala.Function0<java.lang.Object>, java.lang.Object>, int);

That seems to indicate that foo and qux have the same method signature. In other words, I could interpret
=> Int
() => Int
, but
gives me a type mismatch error

scala> import ParamTest._
import ParamTest._

scala> foo(bar,100)
res0: Int = 10

scala> foo(baz,100)
<console>:11: error: type mismatch;
found : (Int, () => Int) => Int
required: (Int, => Int) => Int

EDIT: This is not the same as this question. I'm not asking the practical difference between
call-by-name: => Type
() => Type
. What I'm more interesting in knowing is the internals. How does scala differentiate between the two, when javap or cfr decompilation gives me identical definitions for
; and for

Answer Source

As you've discovered, () => A and => A are not the same thing.

Call by name (i.e. => A) simply means: "delay the evaluation of this method argument." In other words, lazy evaluation.

def f(x: Int, y: => Int) = ???

f(3+5, 2+4)

In this example the addition of 3+5 is done at the call site and the x value is 8. The addition of 2+4, on the other hand, isn't done until y is referenced inside the body of the method f(). If that reference is in an if...else... branch that doesn't get executed then the addition is never done.

This is pretty pointless for simple evaluations like Int addition, but it becomes more meaningful if the argument is an expensive evaluation, of if it's a block of code with side effects.

So, in answer to your question, the meaning of f: (Int, => Int) => Int is: "f takes two arguments and produces an Int, the arguments are 2 Ints, the 2nd of which is evaluated lazily."