5

I am having trouble interpreting "double-rightarrow Type" specified as a function argument without a LHS (left hand side) e.g. () => Int is from () to Int but what does just => Int mean? e.g. see the first argument of foo method below, what is the type of f? Is it (Int, () => Int) => Int?

For the definition of bar, 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 baz.

I could try to reason that f in foo takes the second argument as call by name, and is not from () => Int but that is contradicting that fact that bar and baz 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 as () => Int, but foo(baz,100) 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
              foo(baz,100)
                  ^

EDIT: This is not the same as this question. I'm not asking the practical difference between call-by-name: => Type and () => 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 foo and qux; and for bar and baz.

Community
  • 1
  • 1
vsnyc
  • 2,117
  • 22
  • 35

1 Answers1

6

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."

jwvh
  • 50,871
  • 7
  • 38
  • 64
  • Thanks, I appreciate the explanation. Do you know where I can find more details about this in Scala spec? I tried to work through [Section 4.6](http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html) but am unable to derive the argument without a LHS for the by-name parameter :(, but at least my confusion is cleared, so I can move ahead. – vsnyc Oct 25 '16 at 19:09
  • Well, I don't know the Scala spec, but there are other ways to get this information. As has been pointed out, searching SO for questions that have already been asked is a good place to start. Also, the book "Programming in Scala" (1st edition) is available [online](http://www.artima.com/pins1ed/). Beyond that there are numerous blog posts. Plug a few terms into a search engine and bookmark sites that are useful. – jwvh Oct 25 '16 at 22:30
  • I have read end-to-end [this tutorial](http://www.scala-lang.org/docu/files/ScalaByExample.pdf) by Martin Odersky and also finished his first two courses on Coursera. What I wanted to know is how is Scala distinguishing between the two types `() => A` and `=> A` when decompiling the class file gives me `Function0` in both cases. But this question wasn't clear enough, so I'll ask a new one. You definitely helped with the lazy evaluation part. – vsnyc Oct 25 '16 at 23:07