You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Scala allows the definition of higher-order functions. These are functions that _take other functions as parameters_, or whose _result is a function_. Here is a function `apply` which takes another function `f` and a value `v` and applies function `f` to `v`:
17
-
16
+
Higher order functions take other functions as parameters or return a function as
17
+
a result. This is possible because functions are first-class values in Scala.
18
+
One of the most common examples is the higher-order
19
+
function `map` which is available for collections in Scala.
18
20
```tut
19
-
def apply(f: Int => String, v: Int) = f(v)
21
+
val salaries = Seq(20000, 70000, 40000)
22
+
val doubleSalary = (x: Int) => x * 2
23
+
val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)
20
24
```
25
+
`doubleSalary` is a function which takes a single Int, `x`, and returns `x * 2`. In general, the tuple on the left of the arrow `=>` is a parameter list and the value of the expression on the right is what gets returned. One line 3, the function `doubleSalary` gets applied to each element in the
26
+
list of salaries.
21
27
22
-
_Note: methods are automatically coerced to functions if the context requires this._
28
+
To shrink the code, we could make the function anonymous and pass it directly as
29
+
an argument to map:
30
+
```
31
+
val salaries = Seq(20000, 70000, 40000)
32
+
val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000)
33
+
```
34
+
Notice how `x` is not declared as an Int in the above example. That's because the
35
+
compiler can infer the type based on the type of function map expects. An even more idiomatic way to write the same piece of code would be
23
36
24
37
Here is another example:
25
38
26
39
```tut
27
-
class Decorator(left: String, right: String) {
28
-
def layout[A](x: A) = left + x.toString() + right
40
+
val salaries = Seq(20000, 70000, 40000)
41
+
val newSalaries = salaries.map(_ * 2)
42
+
```
43
+
Since the Scala compiler already knows the type of the parameters (a single Int),
44
+
you just need to provide the right side of the function. The only
45
+
caveat is that you need to use `_` in place of a parameter name (it was `x` in
46
+
the previous example).
47
+
48
+
## Coercing methods into functions
49
+
It is also possible to pass methods as arguments to higher-order functions because
50
+
the Scala compiler will coerce the method into a function.
51
+
```
52
+
case class WeeklyWeatherForecast(temperatures: Seq[Double]) {
Here the method `convertCtoF` is passed to forecastInFahrenheit This is possible because the compiler coerces `convertCtoF` to the function `x => convertCtoF(x)` (note: `x` will
60
+
be a generated name which is guaranteed to be unique within its scope).
61
+
62
+
## Functions that accept functions
63
+
One reason to use higher-order functions is to reduce redundant code. Let's say you wanted functions that could raise someone's salaries by various factors. Without creating a higher-order function,
val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String
42
121
```
43
122
44
-
In this example, the method `decorator.layout` is coerced automatically to a value of type `Int => String` as required by method `apply`. Please note that method `decorator.layout` is a _polymorphic method_ (i.e. it abstracts over some of its signature types) and the Scala compiler has to instantiate its method type first appropriately.
123
+
Notice the return type of urlBuilder `(String, String) => String`. This means that
124
+
the returned anonymous function takes two Strings and returns a String. In this case,
125
+
the returned anonymous function is `(endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query"`.
0 commit comments