2

I'm trying to figure out the difference between def and var/val when declaring a function in Scala.

Say we have a function:

scala> def f(x: Int) = { x * 2 }
f: (x: Int)Int

And another function g:

scala> var g = (x:Int) => x*2
g: Int => Int = <function1>

Apparently they are the same in the following way:

scala> f(2)
res0: Int = 4

scala> g(2)
res1: Int = 4

However, I could do

g = f
g: Int => Int = <function1>

but not

scala> f = g
<console>:13: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
val $ires6 = f
             ^
<console>:10: error: reassignment to val
       f = g
         ^

Question 1: why does this happen? I'm guessing that def maps to val.

Question 2: if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?

I then try:

scala> def three( timetwo:(Int) => Int ) = { timetwo(3) } 
three: (timetwo: Int => Int)Int

scala> three(g)
res47: Int = 6

scala> three(f)
res48: Int = 6

Question 3: does it mean (x: Int)Int is the same as Int => Int = <function1>? If so, is there some situation that we should favor one over the other?

Things is getting wired with the _ (underscore),

scala> three(f _)
res49: Int = 6

scala> three(g _)
<console>:11: error: type mismatch;
found   : () => Int => Int
required: Int => Int
          three(g _)
                ^

Question 4: why does this happen? What's the usage of _(underline) in Scala?

Chu-Cheng Hsieh
  • 191
  • 1
  • 7
  • possible duplicate of [Two ways of defining functions in Scala. What is the difference?](http://stackoverflow.com/questions/5009411/two-ways-of-defining-functions-in-scala-what-is-the-difference) – Jörg W Mittag Jan 17 '15 at 02:44
  • http://stackoverflow.com/questions/2529184/difference-between-method-and-function-in-scala – Maxim Jan 18 '15 at 23:59

1 Answers1

6

why does this happen? I'm guessing that def maps to val.

def is a method (in JVM terms) so it doesn't make sense to assign it.

The parser is then confused and it ultimately tries to save the day by interpreting the assignment f = g as

val $ires6 = f
f = g

Both statements are illegal, so you get two errors:

  • you can't assign a method to a val without an explicit type annotation or a _ expansion - see below)
  • you can't reassign a val (in case you are wondering, $ires6 is a fresh val introduced by the REPL)

if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?

The difference is that val cannot be reassigned (i.e. it's a constant reference), whereas var can (i.e. it's a mutable reference).

More on the subject here: What is the difference between a var and val definition in Scala?

does it mean (x: Int)Int is the same as Int => Int = ? If so, is there some situation that we should favor one over the other?

Methods and functions are not the same, although the compiler does its best to make you believe they are, through a transformation called eta-expansion. In some cases such transformation can be performed automatically, in some others you need to be explicit and trigger it with a trailing _.

In your specific example (passing a method where a function is expected) the expansion can been performed automatically.

You can read this Q/A for a more in-depth discussion about which style to prefer.

why does this happen? What's the usage of _(underline) in Scala?

The underscore (_) has many uses in scala, one of which is the one I mentioned before, i.e. triggering the eta expansion of a method into a function.

That's a special syntax for methods, so you simply can't apply it to a function, as it would make no sense.

That's why you can do f _ (which will turn the f method into a function), but you can't do g _ (since g it's already a function).

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235