From 33ee48e616e7da092dfa67b54ba7ade0be20cbd7 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 28 Jan 2019 10:15:59 +0100 Subject: [PATCH] Update eta-expansion-spec.md --- .../changed-features/eta-expansion-spec.md | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/docs/docs/reference/changed-features/eta-expansion-spec.md b/docs/docs/reference/changed-features/eta-expansion-spec.md index cfbab5c6c330..c3d1a8001150 100644 --- a/docs/docs/reference/changed-features/eta-expansion-spec.md +++ b/docs/docs/reference/changed-features/eta-expansion-spec.md @@ -6,29 +6,19 @@ title: "Automatic Eta Expansion - More Details" ### Motivation Scala maintains a convenient distinction between _methods_ and _functions_. -Methods are part of the definition of a class that can be invoked in objects while functions are complete objects themselves, making them first-class entities. For example they can be assigned in variables. -These two mechanisms are bridged in Scala by a mechanism called _eta-expansion_ in literature also called eta-abstraction). -According to this, methods can be turned into functions. -The intuition behind this, is that if we have a function `f(x)` and we need to pass it around -we can either pass its name `f` or a function `x => f(x)` which expresses the idea that two functions -are equivalent if and only if they give the same result for all arguments. +Methods are part of the definition of a class that can be invoked in objects while functions are complete objects themselves, making them first-class entities. For example, they can be assigned to variables. +These two mechanisms are bridged in Scala by a mechanism called _eta-expansion_ (also called eta-abstraction), which converts a reference to a method into a function. Intuitively, a method `m` can be passed around by turning it into an object: the function `x => m(x)`. -Consequently, the essense of eta-expansion is captured in the following snippet. -Imagine that the `val` is generated by the compiler, when the programmer writes ```f = m```. -The right-hand side is not a function so the compiler performs _automatic eta-expansion_: +In this snippet which assigns a method to a `val`, the compiler will perform _automatic eta-expansion_, as shown in the comment: ```scala def m(x: Int, y: String) = ??? -val f = m // generates val f = (x: Int, y: String) => m(x, y) +val f = m // becomes: val f = (x: Int, y: String) => m(x, y) ``` -In Scala, previously, a method reference `m` was converted to a function value -only if the expected type was a function type. If that was not the -case, one had to write `m _` to force the conversion. +In Scala 2, a method reference `m` was converted to a function value only if the expected type was a function type, which means the conversion in the example above would not have been triggered, because `val f` does not have a type ascription. To still get eta-expansion, a shortcut `m _` would force the conversion. -For methods with one or more parameters like in the example above, this restriction has now been -dropped. The syntax `m _` is no longer needed and will be deprecated in the -future. +For methods with one or more parameters like in the example above, this restriction has now been dropped. The syntax `m _` is no longer needed and will be deprecated in the future. ## Automatic eta-expansion and partial application In the following example `m` can be partially applied to the first two parameters. @@ -70,17 +60,16 @@ val bar: implicit Double => Float = foo(3) // val bar: implicit Double => Float ## Rules -- If `m` has one or more parameters, we always eta-expand -- If `m` is nullary (i.e. has type `()R`): +- If `m` has an argument list with one or more parameters, we always eta-expand +- If `m` is has an empty argument list (i.e. has type `()R`): 1. If the expected type is of the form `() => T`, we eta expand. 2. If m is defined by Java, or overrides a Java defined method, we insert `()`. 3. Otherwise we issue an error of the form: -Unapplied nullary methods are only converted to functions when a function type is expected. -You need to either apply the method to `()`, or convert it to a function with `() => m()`. -The syntax `m _` is deprecated. +Thus, an unapplied method with an empty argument list is only converted to a function when a function type is expected. It is considered best practice to either explicitly apply the method to `()`, or convert it to a function with `() => m()`. + +The method value syntax `m _` is deprecated. ### Reference For more info, see [PR #2701](https://github.com/lampepfl/dotty/pull/2701). -