Scala Language


Functions All Versions

2.10.1
2.10.2
2.10.3
2.11.5
2.10.4
2.11.0
2.11.1
2.11.2
2.11.4
2.10.5
2.11.6
2.11.7
2.10.6
2.11.8

This draft deletes the entire topic.

inline side-by-side expand all collapse all

Examples

  • 1

    In general, functions in Scala have the following pattern:

    def foo([parameters]): [return type] = expression
    

    A simple example is the sum of two numbers:

    def sum(a: Int, b: Int): Int = {
       return a + b
    }
    

    The return statement can be omitted since Scala always returns the value of the last expression in a function:

    def sumWithoutReturn(a: Int, b: Int): Int = {
       a + b
    }
    

    Because Scala expects an expression after the equal sign, it is possible to shorten this example to the following:

    def sumShort(a: Int, b: Int): Int = a + b
    

    The return type can be omitted as well since Scala knows what it has to expect as return type (if you add two integers the sum will also be an integer). This feature is called type inference.

    def sumShortest(a: Int, b: Int) = a + b
    

    If you don't want to return a value and you want to indicate this, you can use Unit as return type which is similar to void in Java.

    def printSum(a: Int, b: Int): Unit = println(a + b)
    
  • 1

    Anonymous functions are lightweight functions, which can be defined without a need to assign a name.

    The following is an anonymous function which takes in two integers and returns their sum.

    (x: Int, y: Int) => x + y
    

    They can be assigned to vals :

    val sum = (x: Int, y: Int) => x + y
    

    They are mainly used however as arguments to other functions. For instance, the map function on collections expects another function as its argument :

    // Returns Seq("FOO", "BAR", "QUX")
    Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)
    

    The types of the arguments of the anonymous function can be omitted, they will be infered automatically :

    Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)
    

    If there is just one argument, parenthesis around it can be omitted too :

    Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)
    

    Underscores shorthand

    There is an even shorter syntax, which doesn't require you to name the arguments. The above snippet can also be written :

    Seq("Foo", "Bar", "Qux").map(_.toUpperCase)
    

    _represents the anonymous function arguments positionally. So if you have an anonymous function with multiple parameters, each occurrence of _ will refer to a different argument. For instance, the two following expressions are equivalent :

    // Returns "FooBarQux" in both cases
    Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
    Seq("Foo", "Bar", "Qux").reduce(_ + _)
    

    With this shorthand however you can not refer to the same argument twice, nor refer to them in a different order.

    Anonymous function with zero parameters

    If you want to create a value for an anonymous function which does not take parameters, leave the parameter list blank:

    val sayHello = () => println("hello")
    
  • Improvements requested by implicitdef:

    • This example does not sufficiently illustrate the point and needs to be edited to provide more details. - 10h ago
      Comments:
      • We should also illustrate clearly that if the argument is never called (like when it is used in a certain branch of a if), it is never evaluated at all. - implicitdef
    1

    Call-by-name parameters are evaluated each time they are used within a function, rather than once at the point the function is applied.

    def callByValue(x: Int) = {
      println(s"Inside function - arg = $x")
      x
    }
    
    callByValue({println("Evaluating byValue argument"); 5})
    // Evaluating byValue argument
    // Inside function - arg = 5
    // res0: Int = 5
    
    def callByName(x: => Int) = {
      println(s"Inside function - arg = $x")
      x
    }
    
    callByName({println("Evaluating byName argument"); 5})
    // Evaluating byName argument
    // Inside function - arg = 5
    // Evaluating byName argument
    // res1: Int = 5
    

I am downvoting this example because it is...

Syntax

Syntax

Parameters

Parameters

Remarks

Remarks

Still have question about Functions? Ask Question

Function Declaration

1

In general, functions in Scala have the following pattern:

def foo([parameters]): [return type] = expression

A simple example is the sum of two numbers:

def sum(a: Int, b: Int): Int = {
   return a + b
}

The return statement can be omitted since Scala always returns the value of the last expression in a function:

def sumWithoutReturn(a: Int, b: Int): Int = {
   a + b
}

Because Scala expects an expression after the equal sign, it is possible to shorten this example to the following:

def sumShort(a: Int, b: Int): Int = a + b

The return type can be omitted as well since Scala knows what it has to expect as return type (if you add two integers the sum will also be an integer). This feature is called type inference.

def sumShortest(a: Int, b: Int) = a + b

If you don't want to return a value and you want to indicate this, you can use Unit as return type which is similar to void in Java.

def printSum(a: Int, b: Int): Unit = println(a + b)

Anonymous Functions

1

Anonymous functions are lightweight functions, which can be defined without a need to assign a name.

The following is an anonymous function which takes in two integers and returns their sum.

(x: Int, y: Int) => x + y

They can be assigned to vals :

val sum = (x: Int, y: Int) => x + y

They are mainly used however as arguments to other functions. For instance, the map function on collections expects another function as its argument :

// Returns Seq("FOO", "BAR", "QUX")
Seq("Foo", "Bar", "Qux").map((x: String) => x.toUpperCase)

The types of the arguments of the anonymous function can be omitted, they will be infered automatically :

Seq("Foo", "Bar", "Qux").map((x) => x.toUpperCase)

If there is just one argument, parenthesis around it can be omitted too :

Seq("Foo", "Bar", "Qux").map(x => x.toUpperCase)

Underscores shorthand

There is an even shorter syntax, which doesn't require you to name the arguments. The above snippet can also be written :

Seq("Foo", "Bar", "Qux").map(_.toUpperCase)

_represents the anonymous function arguments positionally. So if you have an anonymous function with multiple parameters, each occurrence of _ will refer to a different argument. For instance, the two following expressions are equivalent :

// Returns "FooBarQux" in both cases
Seq("Foo", "Bar", "Qux").reduce((s1, s2) => s1 + s2)
Seq("Foo", "Bar", "Qux").reduce(_ + _)

With this shorthand however you can not refer to the same argument twice, nor refer to them in a different order.

Anonymous function with zero parameters

If you want to create a value for an anonymous function which does not take parameters, leave the parameter list blank:

val sayHello = () => println("hello")

Call-by-name and call-by-value

1

Call-by-name parameters are evaluated each time they are used within a function, rather than once at the point the function is applied.

def callByValue(x: Int) = {
  println(s"Inside function - arg = $x")
  x
}

callByValue({println("Evaluating byValue argument"); 5})
// Evaluating byValue argument
// Inside function - arg = 5
// res0: Int = 5

def callByName(x: => Int) = {
  println(s"Inside function - arg = $x")
  x
}

callByName({println("Evaluating byName argument"); 5})
// Evaluating byName argument
// Inside function - arg = 5
// Evaluating byName argument
// res1: Int = 5

Currying

0

Currying, according to Wikipedia,

is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions.

Concretely, in terms of scala types, in the context of a function that take two arguments, (has arity 2) it is the conversion of

val f: (A, B) => C // a function that takes two arguments of type `A` and `B` respectively 
                   // and returns a value of type `C`

to

val curriedF: A => B => C // a function that take an argument of type `A` 
                          // and returns *a function* 
                          // that takes an argument of type `B` and returns a `C`

So for arity-2 functions we can write the curry function as:

def curry[A, B, C](f: (A, B) => C): A => B => C = { 
  (a: A) => (b: B) => f(a, b) 
}

Usage:

val f: (String, Int) => Double = {(_, _) => 1.0}
val curriedF: String => Int => Double = curry(f)
f("a", 1)        // => 1.0
curriedF("a")(1) // => 1.0

Scala gives us a few language features that help with this:

  1. You can write curried functions as methods. so curriedF can be written as:
def curriedFAsAMethod(str: String)(int: Int): Double = 1.0
val curriedF = curriedFAsAMethod _
  1. You can un-curry (i.e. go from A => B => C to (A, B) => C) using a standard library method: Function.uncurried
val f: (String, Int) => Double = Function.uncurried(curriedF)
f("a", 1) // => 1.0

Simple Currying

0
def add(a: Int)(b: Int): Int = a + b
add: (Int) => (Int) => Int
val add9 = add(9) _
add9: Int => Int = <function1>
add9(1)
res0: Int = 10

Topic Outline