Scala "def" method declaration: Colon vs equals
Asked Answered
H

6

6

I am at the early stages of learning Scala and I've noticed different ways to declare methods.

I've established that not using an equals sign makes the method a void method (returning a Unit instead of a value), and using an equals sign returns the actual value so

def product(x: Int, y: Int) {
  x*y
}

will return () (Unit), but

def product(x: Int, y: Int) = {
  x*y
}

will return the product of the two arguments(x*y)

I've noticed a third way of declaring methods - with a colon. Here is an example

def isEqual(x: Any): Boolean

How does this differ from the = notation? And in what situations will it be best to use this way instead?

Helmut answered 31/10, 2014 at 8:12 Comment(1)
Just for reference, although many answers correctly state that procedure syntax (no = between closing ) of args and opening { of method body) is (silently) deprecated, it is not true for everyone that the = is "easy to overlook". Personally I find : Unit = easy to overlook as compared to a method that returns something useful; it doesn't jump out at me as something that will surely cause side effects. That said, the no-equals syntax is supposed to go away eventually, so perhaps best not to get too fond of it.Wakefield
I
12

When you use colon (and use equal) you explicitly define return type of method.

// method return Boolean value
def m(a : Int) : Boolean = a > 0 

When you don't use colon and use equal you allow scala compiler inferring return type itself.

// method has return type of last expression (Boolean)
def m(a : Int) = a > 0 

When you use neither colon nor equal your method has return type of Unit class.

// method has Unit return type
def m(a : Int){ 
    a > 0 
}
Implicate answered 31/10, 2014 at 8:14 Comment(0)
O
1

if you don't want the return type then you used

scala> def product(x: Int, y: Int) { //in lack of = it explicit uses Unit 
     |   x*y
     | }
product: (x: Int, y: Int)Unit
//equivalent to below
scala> def product(x: Int, y: Int):Unit={ 
     |   x*y
     | }
product: (x: Int, y: Int)Unit

and when you write

scala> def product(x: Int, y: Int) = {  //here it explicit detect return type
     |   x*y
     | }
product: (x: Int, y: Int)Int
//equivalent to below
scala> def product(x: Int, y: Int):Int = {
     |   return x*y
     | }
product: (x: Int, y: Int)Int
Odericus answered 31/10, 2014 at 8:24 Comment(0)
M
1

Others have perfectly explained the differences between the different declarations:

def foo: Boolean = true // explicitly declare the return type

and

def foo = true // let the compiler to implicitly infer Boolean

That being said, I have to warn you against

def foo { }

This is called procedure-syntax, and you should never use it, as it's has been already deprecated (since Oct 29, 2013), although you'll get a deprecation warning only under the -Xfuture flag.

Whenever you have to declare a method returning Unit (which you should avoid as much as possible, since it means you're relying on side-effects), use the following syntax

def foo: Unit = { }

Also, as a personal advice, explicitly annotating return types makes your code often more readable and helps you in catching errors early. You know what the function should return, so explicitly annotating the type allows the compiler to check that the implementation returns an appropriate value, right at the declaration position (if you use the function you will catch an error eventually, but perhaps far from where the error really is).

Also, when declaring an abstract member, you'd better also annotate the types

trait {
  def foo
}

is legal, but the type of foo is automatically inferred to be Unit, which almost never what you want.

Instead, do

trait {
  def foo: Boolean
}
Mencher answered 31/10, 2014 at 8:58 Comment(0)
D
0

def foo(arg) { sideEffects() } is equivalent to def foo(arg) = { sideEffects(); Unit }. It is bad style because it hides your intention. (It's easy to overlook the missing =). I recommend you don't use it.

def foo(arg) = { expression } is a method that implicitly resolves to the type of the expression and is good style.

def foo(arg): Type is an abstract method definition with an explicit type. It is not equivalent to the other two examples, as no implementation is provided.

Dilapidated answered 31/10, 2014 at 8:45 Comment(0)
C
0

1) The procedure syntax is deprecated from scala-2.11, avoid it.

def product(x: Int, y: Int) {
    x*y
}
// It always returns Unit. 
// creates confusion for most beginners. deprecated for good.

2) The type inference syntax, mostly used with small/private methods.

def product(x: Int, y: Int) = {
    x*y
}

It is a help from the compiler, but sometimes compiler's inference may be different from what you think.

3) The type annotation syntax.

def product(x: Int, y: Int): Int = {
    x*y
}

For public APIs it is good practice to specify return type explicitly.

In some cases it is mandatory to specify return type. For instance:

  • when defining recursive methods.

  • when compiler's inference is more specific but you need generic return type (Map in place of HashMap).

  • To override compiler's inference. def getId(): Long = 1

  • If return is used anywhere in the method body.

Contrast answered 31/10, 2014 at 8:58 Comment(0)
P
0

In Scala a function is defined as

def product(x: Int, y: Int): Int = {
  x*y
}

but there there are few "shortcuts" that can be used

  1. Since scala have good type Inference you can omit the type (unless the function is recursion one):

    def product(x: Int, y: Int) = { x*y }

  2. Everything is an expression. so function must return value. The last line of block of code is the return value. so if you use curved brackets {} the last line will be return. if the function has only one line there is no need for the curved brackets.

    def product(x: Int, y: Int) = x*y

  3. Since everything has to return a value "No value" is actually Unit. So if you dont want to return meaningful value (which mean you do some side effects) then use Unit as the return value:

    def product(x: Int, y: Int): Unit = x*y

  4. Using functions without the equal sign is just another way to return Unit (this also named "procedure syntax":

    def product(x: Int, y: Int) { x*y }

Power answered 31/10, 2014 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.