lindelof
lindelof

Reputation: 35240

What does it mean when I use def to define a field in Scala?

What exactly is the difference between:

scala> def foo = 5
foo: Int

and

scala> def foo() = 5
foo: ()Int

Seems that in both cases, I end up with a variable foo which I can refer to without parenthesis, always evaluating to 5.

Upvotes: 7

Views: 1119

Answers (5)

Steven Jern
Steven Jern

Reputation: 11

I'm surprised that nobody mentioned anything about the laziness difference. While val is evaluated only once at the time of definition, def is evaluated only when we access it and evaluated every-time we access it. See example below:

scala> def foo = {
     | println("hi")
     | 5
     | }
foo: Int

scala> val onlyOnce = foo
scala> def everyTime = foo

scala> onlyOnce
res0: Int = 5
scala> onlyOnce
res1: Int = 5

scala> everyTime
hi
res2: Int = 5
scala> everyTime
hi
res3: Int = 5

Upvotes: 0

Landei
Landei

Reputation: 54574

Additionally to the answers already given I'd like to stress two points:

  • The possibility to define methods without a parameter list is a way to realize the Uniform Access Principle. This allows to hide the difference between fields and methods, which makes later implementation changes easier.

  • You can call a method defined as def foo() = 5 using foo, but you can't call a method defined as def foo = 5 using foo()

Upvotes: 4

Alexey Romanov
Alexey Romanov

Reputation: 170733

What does it mean when I use def to define a field in Scala

You can't define a field using def.

Seems that in both cases, I end up with a variable foo which I can refer to without parenthesis, always evaluating to 5.

No, in both cases you end up with a method foo, which you can call without parentheses.

To see that, you can use javap:

// Main.scala
object Main {
  def foo1 = 5
  def foo2() = 5
}


F:\MyProgramming\raw>scalac main.scala

F:\MyProgramming\raw>javap Main
Compiled from "main.scala"
public final class Main extends java.lang.Object{
    public static final int foo2();
    public static final int foo1();
}

However, see http://tommy.chheng.com/index.php/2010/03/when-to-call-methods-with-or-without-parentheses-in-scala/

Upvotes: 4

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297185

Before anything else is said, def does not define a field, it defines a method.

In the second case, you can omit parenthesis because of a specific feature of Scala. There are two differences of interest here: one mechanical, and one of recommended usage.

Beginning with the latter, it is recommended usage to use empty parameter list when there are side effects. One classic example is close(). You'd omit parenthesis if there are no side effects to calling the element.

Now, as a practical difference -- beyond possible weird syntactic mix-ups in corner cases (I'm not saying there are, just conjecturing) -- structural types must follow the correct convention.

For example, Source had a close method without parenthesis, meaning a structural type of def close(): Unit would not accept Source. Likewise, if I define a structural method as def close: Unit, then Java closeable objects will not be accepted.

Upvotes: 7

Dave Griffith
Dave Griffith

Reputation: 20515

You're not defining a variable in either case. You're defining a method. The first method has no parameter lists, the second has one parameter list, which is empty. The first of these should be called like this

val x = foo 

while the second should be called like this

val x = foo()

However, the Scala compiler will let you call methods with one empty parameter list without the parentheses, so either form of call will work for the second method. Methods without parameter lists cannot be called with the parentheses

The preferred Scala style is to define and call no-argument methods which have side-effects with the parentheses. No-argument methods without side-effects should be defined and called without the parentheseses.

If you actually which to define a variable, the syntax is

val foo = 5

Upvotes: 17

Related Questions