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

Higher #681

wants to merge 6 commits into from

Conversation

travissarles
Copy link
Contributor

No description provided.

---

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`:
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”.

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.

}
```

Execution yields the output:
Here the method `convertCtoF` is passed to getForecastInFahrenheit This is possible because the compiler coerces `convertCtoF` to the function `_ => convertCtoF(_)`.
Copy link
Contributor

Choose a reason for hiding this comment

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

_ has a lot of meanings in Scala, whether it is placed on the left or on the right of an => (or =), which might lead to confusions… Your example would not work because the first _ defines a function with one ignored parameter, and the second one means “a function that takes one parameter and applies it to convertCtoF”.

But, again, I would not use _ here and go with a simpler version: x => convertCtoF(x). (Where x is actually a generated name which is guaranteed to be unique and to not clash with names that are already in scope)


def filesEndingWith(query: String) =
for (file <- filesHere; if file.getName.endsWith(query))
yield
Copy link
Contributor

Choose a reason for hiding this comment

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

yield file

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, this example makes use of the for yield syntax, which may not be familiar to the reader.

What about staying in the context of salaries and define the following methods?

def smallPromotion(salaries: List[Double]): List[Double] =
  salaries.map(salary => salary * 1.1)

def greatPromotion(salaries: List[Double]): List[Double] =
  salaries.map(salary => salary * math.log(salary))

Which can then be generalized as follows:

def promotion(salaries: List[Double], promotionFunction: Double => Double): List[Double] =
  salaries.map(promotionFunction)

def apply(f: Int => String, v: Int) = f(v)
val decorator = new Decorator("[", "]")
println(apply(decorator.layout, 7))
def getForecastInFahrenheit() = temperatures.map(convertCtoF) // <-- passing the method convertCtoF
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you should always add the return type of your method definitions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, a convention in Scala is to put parens to methods that take no parameter only if this method actually performs side-effects. Since getForecastInFahrenheit is pure, you should remove the parens to its definition. Also, I would omit the get prefix, which is not common in Scala: def forecastInFahrenheit: Double.

val newSalaries = salaries.map(doubleSalary) // List(40000, 140000, 80000)
```
In this case, the function `doubleSalary` gets applied to each element in the
list of salaries. A more idiomatic way to write the same piece of code would be
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 explain a little bit more what the x => … syntax means?

```

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.
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.

@jvican
Copy link
Member

jvican commented Feb 13, 2017

Can you please rebase on top of #685?

@mpociecha
Copy link
Contributor

FYI you don't need to close PRs and create new ones. It's possible to push once again with -f flag. HTH

@travissarles
Copy link
Contributor Author

Unfortunately I messed up the branching and the pull requests were including stuff from other branches so I started from scratch to clean it up.

@travissarles
Copy link
Contributor Author

I'll use the push -f if i need to update a pr. Thanks for the tip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants