Well, here's the full breakdown.
def value: Int = ??? def method(): Int = ??? def f1(f: () => Int) = ??? def f2(f: => Int) = ??? f1(value) // fails f1(method) // works f2(value) // works f2(method) // works with a warning "empty-paren method accessed as parameterless"
This error fails because f1 expects the function Unit => Int, but it is assigned the value Int.
f1 (method)
This works because f1 expects a function and a method is given. Here's the difference: the method is not a value in Scala; it cannot exist by itself and is an attribute of the context that it defines (class, trait, object, etc.). Function is the value; it can be stored in a collection, taken as an argument in another function, returned from a function, etc. When the compiler expects a function and receives a method, it executes the eta extension. Given the function, for example. f: (a: Int, b: Int) => Int , this extension is the process of creating another layer around it, keeping the signature, so it becomes (a: Int, b: Int) => f(a, b) . This method is useful because we can turn methods into a function. For some method, def f(a: Int): Int = ??? we can execute an eta extension to create a function of the type Int => Int: (a: Int) => f(a) . I wrote a blog post about this a while ago, if you're interested.
2 (value)
It works without surprises, but note that the passed value is accessed every time it is used in the function body.
2 (method)
It works, but with a warning that we are calling a method that is given with an empty bracket without using parentheses. It is good practice to use methods without parentheses (e.g. f ), when they simply represent a value, but one that is recounted every time it is accessed, for example. numberOfUpvotes and use methods with an empty bracket (for example, f() ) when some side effect is performed, and therefore the method is not idempotent, for example. createSnapshot() (again, this should not be present in purely functional code).
Tip: do not burden your mind with what to replace for. Do not use replacements. If something needs a function, provide it with a function. If a value is required for this, specify a value. If the method is defined without parsers, call it without parsers. If it has parens, call it with parens.
If you need to switch from a method to a function, and the compiler expects a function, this extension will happen automatically. If it does not expect a function, you need to do it manually.
def f(): Int = ??? val a = f // no function context; a is a string val b: () => Int = f // b is a function Unit => Int val c = f2 _ // c is a function Unit => Int
The latter case is a partially applied function. I feel like I'm too wide right now, so I will stay here. Hope this helps.