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`:
15
-
15
+
Higher order functions take other functions as parameters or return a function as
16
+
a result. This is possible because functions are first-class values in Scala.
17
+
One of the most common examples is the higher-order
18
+
function `map` which is available for collections in Scala.
16
19
```tut
17
-
def apply(f: Int => String, v: Int) = f(v)
20
+
val salaries = Seq(20000, 70000, 40000)
21
+
val doubleSalary = (x: Int) => x * 2
22
+
val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)
18
23
```
24
+
`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
25
+
list of salaries.
19
26
20
-
_Note: methods are automatically coerced to functions if the context requires this._
27
+
To shrink the code, we could make the function anonymous and pass it directly as
28
+
an argument to map:
29
+
```
30
+
val salaries = Seq(20000, 70000, 40000)
31
+
val newSalaries = salaries.map(x => x * 2) // List(40000, 140000, 80000)
32
+
```
33
+
Notice how `x` is not declared as an Int in the above example. That's because the
34
+
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
21
35
22
-
Here is another example:
23
-
24
36
```tut
25
-
class Decorator(left: String, right: String) {
26
-
def layout[A](x: A) = left + x.toString() + right
37
+
val salaries = Seq(20000, 70000, 40000)
38
+
val newSalaries = salaries.map(_ * 2)
39
+
```
40
+
Since the Scala compiler already knows the type of the parameters (a single Int),
41
+
you just need to provide the right side of the function. The only
42
+
caveat is that you need to use `_` in place of a parameter name (it was `x` in
43
+
the previous example).
44
+
45
+
## Coercing methods into functions
46
+
It is also possible to pass methods as arguments to higher-order functions because
47
+
the Scala compiler will coerce the method into a function.
48
+
```
49
+
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
57
+
be a generated name which is guaranteed to be unique within its scope).
58
+
59
+
## Functions that accept functions
60
+
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
40
116
```
41
117
42
-
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.
118
+
Notice the return type of urlBuilder `(String, String) => String`. This means that
119
+
the returned anonymous function takes two Strings and returns a String. In this case,
120
+
the returned anonymous function is `(endpoint: String, query: String) => s"$schema$domainName/$endpoint?$query"`.
0 commit comments