Skip to content

Higher #681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Finished sentences
  • Loading branch information
travissarles committed Feb 10, 2017
commit 1c534f1b3e71dd1de09a86318e7a7fa5f234f68c
33 changes: 14 additions & 19 deletions tutorials/tour/higher-order-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@ previous-page: anonymous-function-syntax
assumed-knowledge: sequence-comprehensions
---

Higher order functions are functions that take other functions are parameters
or whose result is a function. They can be useful for reducing duplicate code
when you want to create multiple functions with only slightly different functionality.

Higher order functions take other functions as parameters or return a function as
a result. This is possible because functions are first-class objects in Scala.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say “first-class values” instead of “objects”.

One of the most common examples is the higher-order
function `map` available for collections in Scala.
function `map` which is available for collections in Scala.
```tut
val salaries = Seq(20000, 70000, 40000)
val doubleSalary = (x: Int) => x * 2
Expand All @@ -29,8 +27,8 @@ list of salaries. A more idiomatic way to write the same piece of code would be
val salaries = Seq(20000, 70000, 40000)
val newSalaries = salaries.map(_ * 2)
```
The Scala compiler already knows the type of the parameters (a single Int) so
you just need to provide the right side of the function doubleSalary. The only
The Scala compiler already knows the type of the parameters (a single Int) that function argument
for `map` needs. Therefore you just need to provide the right side of the function `doubleSalary`. The only
caveat is that you need to use `_` in place of a parameter name (it was `x` in
the previous example).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, you don’t have to use _. You could also write salaries.map(x => x * 2).

Actually, I would first use salaries.map(x => x * 2), and then later explain that there is a shorter notation with _ * 2.


Expand All @@ -48,9 +46,7 @@ case class WeeklyWeatherForecast(temperatures: Seq[Double]) {
Here the method `convertCtoF` is passed to getForecastInFahrenheit This is possible because the compiler coerces `convertCtoF` to `_ => convertCtoF(_)`, i.e. a function.

## Functions that accept functions
Let's say you wanted a function that could either search for files by directory,
by regular expression, or by a substring.
by file name, extension, or by contents. Without creating a higher-order function,
One reason to use higher-order functions is to reduce redundant code. Let's say you wanted functions that could either search for files by directory, by regular expression, or by a substring. Without creating a higher-order function,
it might look something like this:

```tut
Expand Down Expand Up @@ -88,7 +84,7 @@ object FileMatcher {
def filesContaining(query: String) =
filesMatching(_.contains(query))

def filesRegex(query: String) =
def filesMatchingRegex(query: String) =
filesMatching(_.matches(query))
}
```
Expand All @@ -100,7 +96,10 @@ created by the `for`/`yield`.
Credit: Odersky, Martin, Lex Spoon, and Bill Venners. Programming in Scala. Walnut Creek, CA: Artima, 2010. Web.

## Functions that return functions
There are certain cases where you

There are certain cases where you want to generate a function. Here's an example
of a method that returns a function.

```tut
def urlBuilder(ssl: Boolean, domainName: String): (String, String) => String = {
val schema = if (ssl) "https://" else "http://"
Expand All @@ -112,11 +111,7 @@ def getURL = urlBuilder(ssl=true, domainName)
val endpoint = "users"
val query = "id=1"
getURL(endpoint, query) // "https://www.example.com/users?id=1": String
val url = getURL(endpoint, query) // "https://www.example.com/users?id=1": String
​```


Caveat
```tut
List(1,3,4).map(MyNum(_))
```
Notice the return type of urlBuilder `(String, String) => String`. This means that
the returned anonymous function takes two Strings and returns a String.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you should emphasize that the syntax at the type level is homogeneous with the syntax at the value level.