Take the 2-minute tour ×

In the following code example, I do not understand why the function fun can be passed as an argument to the method addAction. The method fun is of type Unit, while the method addAction expects a function of type () => Unit.

If fun is of type () => Unit, then why does the compiler complain that fun is of type Unit, when I try to add fun to the actions list: actions = fun :: actions?

package myscala

object MyScala {

  def fun() { println("fun1 executed.") }

  def addAction(a: () => Unit) {
    actions = a :: actions

  var actions: List[() => Unit] = List()

  def main(args: Array[String]) {
    // the following line would produce a compiler error (found: Unit, required: () => Unit), it's OK
    // actions = fun :: actions
    actions = (() => fun) :: actions // OK
    // I would expect the same compiler error here (found: Unit, required: () => Unit), but it's OK why?
    actions.foreach(_()) // prints twice "fun1 executed"
share|improve this question
add comment

3 Answers

up vote 8 down vote accepted

Take this as an introductory example:


val a1 = fun
val a2: () => Unit = fun

Both lines compile and (thanks to type inference) they look equivalent. However a1 is of type Unit while a2 is of type () => Unit... How is this possible?

Since you are not explicitly providing type of a1, compilers interprets fun as a method fun call of type Unit, hence the type of a1 is the same as type of fun. It also means that this line will print fun1 executed.

However, a2 has explicitly declared type of () => Unit. The compiler helps you here and it understands that since the context requires a function of type () => Unit and you provided a method matching this type, it shouldn't call that method, but treat it as first class function!

You are not doomed to specify type of a1 explicitly. Saying:

val a1 = fun _

Do you now understand where your problem is?

share|improve this answer
Yes, I do. This now looks obvious to me (it did not at all at that time). When the compiler is able to infer that a function type is expected, I may simply write fun, otherwise I have to make it explicit that I am passing a function. Thanks for the clear answers to all of you! –  Manu Nov 5 '11 at 16:34
@Manu: Consider accepting an answer that you consider to be the best one (not necessarily this one) –  Tomasz Nurkiewicz Nov 7 '11 at 16:04
add comment

You need to write fun _ in the first case to avoid calling the method and performing eta-expansion instead.

This will work:

actions = (fun _) :: actions

If you don't do this, then fun is evaluated.

For more details, see Section 6.7 (Method Values) of the Scala Language Reference.

As to why fun is not evaluated in the second case, it is because type inference can clearly conclude that addAction expects a function. By the way, the type of fun is technically ()Unit, not Unit, that is, a method type, and not a value type. See Section 3.3.1 in the reference for more.

share|improve this answer
I'd rather recommend a lighter reading: Programming in Scala Chapter 9 –  Jamil Oct 7 '11 at 18:16
add comment

There is a difference between methods and functions. In your case actions is a list of functions. When the compiler knows that a function is required (like in the case of addAction) it can automatically convert a method fun into a function. Now :: is also a method, therefore the compiler also knows that it takes functions as parameters. But the problem is the syntactic sugar of the right-associative operator ::. If you were to call it like a method: actions.::(fun) it will compile (although I can't test it at the moment). When writing fun :: actions the compiler thinks that fun is an expression and therefore evaluates it and since it "returns" a Unit you get your compiler error.


Since I now have the possibility to test my hypothesis (which was wrong) here are your options:

// Usual syntax
actions.::[() => Unit](fun)
actions.::(fun: () => Unit)
actions.::(fun _)
// Operator syntax
(fun: () => Unit) :: actions
(fun _) :: actions
share|improve this answer
actions.::(fun) evaluates to List[Any] = List(()). It is still evaluating the function though. Wonder why is the List[()=>Unit] converted to List[Any]? co-variance? –  Jamil Oct 7 '11 at 18:13
Yes, List[Any] is the most precise type for a list that can contain Units and ()=>Units. The Unit, viewed as () is what evaluating fun returns. –  Philippe Oct 7 '11 at 18:20
I've edited my answer. –  agilesteel Oct 7 '11 at 19:55
add comment

Your Answer


