Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Scala, what are the rules for making closures with underscores?

At first I had believed that using underscores to make closures (e.g. println _) were just shorthand for using an arrow (e.g. x => println x), but I just recently learned that you can also do the following:

def f(a: Int, b: Int) = a + 2 * b
List(1, 2, 3).reduce(f _)

Given my past assumptions, f _ looks like a closure that accepts exactly one argument and passes exactly one argument to f. I assumed it would tell me it couldn't compile because f expects two arguments, and reduce should expect a function with two arguments. But it works as if I had written:

def f(a: Int, b: Int) = a + 2 * b
List(1, 2, 3).reduce((x, y) => f(x, y))

What is going on here? What are the rules for creating closures with underscores?

like image 966
math4tots Avatar asked May 17 '26 04:05

math4tots


1 Answers

Nothing special going on. Method reduce takes a function that takes two Ints and produces an Int, so providing it with an f works fine. Note that when you say f _ that actually expands to x => f x (or, in case of two parameters such as here, (x, y) => f(x, y)). You can also just provide f which will then be used directly, without the extra anonymous function wrapper.

Transforming a method into a function by doing f _ is called eta-expansion (full disclosure: I wrote that article). Difference is subtle; function is a value, while a method is, well, a method that you invoke upon an object it's defined for, e.g. myObject.myMethod. Function can stand alone, be held in collections etc. Defining your method f directly as a function would be val f: (Int, Int) => Int = (a: Int, b: Int) => a + b or, with type inference, val f = (a: Int, b: Int) => a + b.

BTW I don't see how this is a closure.

like image 51
slouc Avatar answered May 19 '26 01:05

slouc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!