Reputation: 35240
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
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
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
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
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
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