def in Scala: equals sign or no equals sign?

When creating a method or procedure in Scala, we start with def, then the name and parameters (if any), optionally the return type, and then the method body. There’s a subtlety here: sometimes the method is equal to the method body, and other times the equals sign is missing. For instance:

class Birthday {
   def howManyMoreDays(from : Date) = {
       // perform some calculation
       daysLeft // return last expression
   def getExcited() {
       println(“Oh yeah! It’s your birthday!”)
       “no one’s listening.”

In this case, howManyMoreDays uses an equals sign between the declaration and the method body. getExcited does not. What is the difference?

Methods without an equals sign always return Unit. Methods with an equals sign between the declaration and the body always return something: the result of the last expression in the method body.

Without an equals sign, you have a procedure, performed for its side effects. With the equals sign, you have a function, performed for its result. Use them accordingly; avoid side effects in functions. The procedure, marked by its lack of an equals sign and its useless return value, is a subtle way to call out side effects, to make it them more explicit.

You cannot return anything but Unit from a method without an equals sign between the declaration and the body. Adding any other return-value declaration is invalid. The last expression here is not returned; no one ever sees the string “no one’s listening.”

If we forget the equals sign in the definition of howManyMoreDays, it will not return anything. To avoid this pitfall, consider explicitly declaring the return type. The following will give a compile error on the method definition, instead of waiting until we use the method:

   def howManyMoreDays(from : Date) : Int // error! need =
       // perform some calculation
       daysLeft // return last expression

For more subtleties in method declarations in Scala, consider def vs val and empty parens vs none.