Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between def foo = {} and def foo() = {} in Scala?

Given the following constructs for defining a function in Scala, can you explain what the difference is, and what the implications will be?

def foo = {} 

vs.

def foo() = {} 

Update

Thanks for the quick responses. These are great. The only question that remains for me is:

If I omit the parenthesis, is there still a way to pass the function around? This is what I get in the repl:

scala> def foo = {} foo: Unit  scala> def baz() = {} baz: ()Unit  scala> def test(arg: () => Unit) = { arg } test: (arg: () => Unit)() => Unit  scala> test(foo) <console>:10: error: type mismatch;  found   : Unit  required: () => Unit               test(foo)                    ^  scala> test(baz) res1: () => Unit = <function0> 

Update 2012-09-14

Here are some similar questions I noticed:

  1. Difference between function with parentheses and without
  2. Scala methods with no arguments
like image 482
Jay Taylor Avatar asked Sep 13 '11 22:09

Jay Taylor


2 Answers

If you include the parentheses in the definition you can optionally omit them when you call the method. If you omit them in the definition you can't use them when you call the method.

scala> def foo() {} foo: ()Unit  scala> def bar {} bar: Unit  scala> foo  scala> bar() <console>:12: error: Unit does not take parameters        bar()           ^ 

Additionally, you can do something similar with your higher order functions:

scala> def baz(f: () => Unit) {} baz: (f: () => Unit)Unit  scala> def bat(f: => Unit) {} bat: (f: => Unit)Unit  scala> baz(foo)      scala> baz(bar) <console>:13: error: type mismatch;  found   : Unit  required: () => Unit        baz(bar)            ^ scala> bat(foo)  scala> bat(bar)  // both ok 

Here baz will only take foo() and not bar. What use this is, I don't know. But it does show that the types are distinct.

like image 152
Luigi Plinge Avatar answered Oct 01 '22 13:10

Luigi Plinge


Let me copy my answer I posted on a duplicated question:

A Scala 2.x method of 0-arity can be defined with or without parentheses (). This is used to signal the user that the method has some kind of side-effect (like printing out to std out or destroying data), as opposed to the one without, which can later be implemented as val.

See Programming in Scala:

Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state).

This convention supports the uniform access principle [...]

To summarize, it is encouraged style in Scala to define methods that take no parameters and have no side effects as parameterless methods, i.e., leaving off the empty parentheses. On the other hand, you should never define a method that has side-effects without parentheses, because then invocations of that method would look like a field selection.

Terminology

There are some confusing terminology around 0-arity methods, so I'll create a table here:

Programming in Scala scala/scala jargon
def foo: Int parameterless methods nullary method
def foo(): Int empty-paren methods nilary method

I sounds cool to say "nullary method", but often people say it wrong and the readers will also be confused, so I suggest sticking with parameterless vs empty-paren methods, unless you're on a pull request where people are already using the jargons.

() is no longer optional in Scala 2.13 or 3.0

In The great () insert, Martin Odersky made change to Scala 3 to require () to call a method defined with (). This is documented in Scala 3 Migration Guide as:

Auto-application is the syntax of calling a nullary method without passing an empty argument list.

Note: Migration document gets the term wrong. It should read as:

Auto-application is the syntax of calling a empty-paren (or "nilary") method without passing an empty argument list.

Scala 2.13, followed Scala 3.x and deprecated the auto application of empty-paren methods in Eta-expand 0-arity method if expected type is Function0. A notable exception to this rule is Java-defined methods. We can continue to call Java methods such as toString without ().

like image 25
Eugene Yokota Avatar answered Oct 01 '22 12:10

Eugene Yokota