Difference between functions and methods in Scala

Scala has a concept of functions and method definitions. These two concepts are often confused and it’s not always clear when to use which.

Consider this example.

Simple method:

def m1(x: Int) = x + x
m1(2)  // 4

Simple function:

val f1 = (x: Int) => x + x
f1(2)  // 4

Both m1 and f1 are called the same way and will produce the same result but when you look closer you will see that these are two different things.

f1  // Int => Int = <function1>
m1  // error: missing argument list for method m1...

Calling f1 without argument will give us the signature of anonymous function.
Our anonymous functions is actually an instance of Function1[Int, Int] that means a function with 1 parameter of type Int and return value of type Int.

f1.isInstanceOf[Function1[Int, Int]]  // Boolean = true  

When calling m1 we will get an error. This is because m1 is not a value, it is a method, something that will produce a value when you call it by providing all required arguments.

Converting method into a function

Method can be converted into a proper function (often referred to as lifting) by calling method with underscore “_” after method name.

val f2 = m1 _  // Int => Int = <function1>

Alternatively you can supply a type and compiler will know what to do.

val f2: Int => Int = m1  // Int => Int = <function1>

Above method to function conversions will always create a new instance of Function1[Int, Int] which is an important observation.

Let’s consider following example. We are creating a sequence of tuples with type (Int, Int => Int). For each tuple we decided to convert our previously defined method into a function. The following will create 10 instances of a function that does the same thing.

for (i <- 0 until 10) yield i -> m1 _

Better approach would be to pass the same instance of the function for each tuple and avoid allocating memory for each instance as in previous approach.

for (i <- 0 until 10) yield i -> f1

When to use methods and when functions

– use functions if you need to pass them around as parameters
– use functions if you want to act on their instances, e.g. f1.compose(f2)(2)
– use methods if you want to use default values for parameters e.g. def m1(age: Int = 2) = ...
– use methods if you just need to compute and return

7 thoughts on “Difference between functions and methods in Scala

  1. Thank you for your explanation, this was very helpful. Question: is there a difference between “val f2 =m1 _ ” and “def f2 = m1 _”? The response from the Scala REPL is not identical:

    scala> val f2 = m1 _
    f2: Int => Int =

    scala> def f2 = m1 _
    f2: Int => Int

    • Hi Ruud,
      The second expressions will evaluate to method that creates a function of Int => Int. Notice when we call f2 in the repl (or assign to a val), result will be Int => Int = function1

      scala> def f2 = m1 _
      f2: Int => Int // everytime you call me, I will create new Int => Int function

      scala> val f3 = f2
      f3: Int => Int = function1 // I’m just and instance of function Int => Int

  2. I found your explanation very, very helpful. I kept getting these strange error messages when assigning functions. Concerning the use of the names ‘method’ and ‘function’, Odersky seems to disagree with you!

    “A function can be invoked with a list of arguments to produce a
    result. A function has a parameter list, a body, and a result type.
    Functions that are members of a class, trait, or singleton object are
    called methods.” (Programming in Scala, Second Edition, Glossary)

    It is getting more and more complicated!

    class A {
    def plus(a: Int, b: Int) = a + b
    }
    val a = new A //> a : method_function.A = method_function$$anonfun$main$1$A$1@1e643faf

    def doe(a: Int, b: Int, f: (Int, Int) => Int) = f(a, b) //> doe: (a: Int, b: Int, f: (Int, Int) => Int)Int
    def plus(a: Int, b: Int) = a + b //> plus: (a: Int, b: Int)Int

    doe(2, 3, a.plus) //> res0: Int = 5
    doe(2, 3, a.plus _) //> res1: Int = 5
    doe(2, 3, plus) //> res2: Int = 5
    doe(2, 3, plus _) //> res3: Int = 5

    I cannot do the assignment ‘val no = plus’ (as you mentioned) but I can pass ‘plus’ to a function call ‘doe(2, 3, plus)’. It is very confusing. Any comments?

    • First of all, thank you for those questions. I made a mistake with naming this article. It should have been “Difference between def and vals in Scala” or something alike.
      To answer your question. I think Scala is doing a conversion into a function when you call `doe(2, 3, plus)`.
      We know that by explicitly supplying function type Scala will convert def to function instance:
      val f: (Int, Int) => Int = plus // (Int, Int) => Int =

      Going back to your example in `doe(2, 3, plus)` third argument here is exactly f: (Int, Int) => Int, so when you pass `plus` as argument it will get converted to a function at call time. Which is equivalent to `doe(2, 3, plus _)` with the difference that you are doing conversion explicitly.

  3. The def/val distinction popped up again. My view is now that I use ‘def’ if I want to adapt the function, and ‘val’ otherwise.

    // I can generate functions for different ‘inc’ values
    def increment(inc:Int) = (x:Int)=>x+inc

    val inc2= increment(2) // the function ‘inc2’ only increments by 2

Leave a Reply

Your email address will not be published. Required fields are marked *