Function basics


Function definitions in Scala are quite flexible and still somewhat concise. Let's look at a simple function definition:

def simpleFunction = 3
println(simpleFunction) //Prints "3".

In the above, the "def" keyword is used to start the definition of the function. After the "def" keyword, the name of the function follows, in this case "simpleFunction". "=" is used to indicate that the function has a return value. After the "=" comes an expression of some sort, indicating the body of the function, which in this case is a 3. We then call the function by simply writing its name, and print the result. Note that since the function has no parameters, we don't use "()" to call it.

Since scopes are expressions, and the last statement in the scope is the result value of the scope, we can write a more advanced function as follows:

def someFunction = {
  val a = 42 - 13*2
println(someFunction) //Prints "256".

The final statement "a*a" is an expression, and thus becomes the result value of the scope, and since the scope is the expression of the function, it becomes the return value of the function. If the final statement in the scope had been a non-expression statement, the return type would have been "Unit", indicating no return value, as seen here:

def printNameFunction = println("Jack Sparrow")
printNameFunction //Prints "Jack Sparrow".

Since the function has no return value, but only has side-effects, it is considered good style to indicate this in the function definition. Instead of using "=" to indicate the body of the function, it is possible to just use a scope:

def printNameFunction2 {println("Captain Haddock")}
printNameFunction2 //Prints "Captain Haddock".

Independent of what value the last expression have, a function that forgoes the "=" will always have the return type "Unit".

The above functions are all a bit boring, since they don't take any arguments. Functions are given argument lists by appending a "()" after the name, like so:

def cubed(a:Int) = a*a*a
def pythagoras(a:Double, b:Double) = math.sqrt(a*a + b*b)
println(cubed(-3)) //Prints "-27".
println(pythagoras(3, 4)) //Prints "5.0".

Each argument in the function is separated by a ",", and calling the functions requires using the "()" and putting the arguments in the right order. Note that the type annotations for the arguments are mandatory.

As you may have noted in the above, the return type was never explicitly declared. The reason is that the Scala compiler can often infer the right return type. If for some reason you want to declare it explicitly, it can be done by putting it between the last parameter list and the start of the body (denoted by either "=" or "{"), like so:

def squared(a:Int):Int = a*a

A common case where the result type needs to be explicitly declared (as of Scala 2.9.1) is for recursive functions, namely functions that call themselves. The basic example is the factorial function:

def factorial(n:Int):Int = {
  if (n == 0) 1
  else n*factorial(n-1)
//ERROR: Does not compile!
/*def factorial(n:Int) = {
  if (n == 0) 1
  else n*factorial(n-1)

Function names


TODO: Syntax regarding names of functions.

Prefix functions


TODO: Syntax regarding prefix and infix functions.

Function precedence


TODO: Syntax regarding function precedence as well as ":".

Function types


TODO: Types of functions, for instance "Int => Double" or "(String => String) => String".