Functions as values are the basis of the collections API and of functional style.
A method is defined with def: def area(w: Double, h: Double = 1.0): Double = w * h. Parameter types are required, the result type is usually inferred but should be written on public methods, and the body is a single expression (or an indented block). Callers can use named arguments in any order (area(h = 2, w = 3)) and skip parameters with defaults.
Methods can have several parameter lists, def add(a: Int)(b: Int) = a + b, useful for type inference, using clauses and passing blocks: retry(3) { ... }. A parameter typed => A is by-name: evaluated each time it's used rather than before the call, which lets you write control-structure-like methods.
A function value (lambda) is written (x: Int) => x * 2. When the expected type is known you can drop the types, xs.map(x => x * 2), or use the placeholder shorthand xs.map(_ * 2). Function types read naturally: Int => Int, (String, Int) => Boolean.
Methods are converted to functions automatically when a function is expected (eta-expansion), so xs.map(area(_, 2)) or names.foreach(println) just work.
Varargs use *: def sum(xs: Int*) = xs.sum, and a sequence is passed with sum(list*).
Example
def area(w: Double, h: Double = 1.0): Double = w * h
println(area(3)) // 3.0
println(area(h = 2, w = 5)) // 10.0
val double: Int => Int = x => x * 2
val add = (a: Int, b: Int) => a + b
println(List(1, 2, 3).map(double)) // List(2, 4, 6)
println(List(1, 2, 3).map(_ + 10)) // List(11, 12, 13)
println(List(4, 5).reduce(add)) // 9
def twice(f: Int => Int, x: Int): Int = f(f(x))
println(twice(_ * 3, 2)) // 18
def logIf(enabled: Boolean)(msg: => String): Unit =
if enabled then println(msg)
logIf(false) { println("never evaluated"); "expensive" }
logIf(true)("cheap") // cheap
def sum(xs: Int*): Int = xs.sum
println(sum(1, 2, 3) + sum(List(4, 5)*)) // 15Remember
defdefines methods; named and default arguments make calls clear- Lambdas:
x => x * 2or the placeholder_ * 2 => Aparameters are by-name, evaluated only when used- Methods turn into functions automatically when needed
Watch out for
- Using
_twice expecting the same argument:_ * _is a two-argument function.