Skip to content

Commit 0cdf13a

Browse files
Merge pull request #9458 from tegonal/doc-extension-methods
doc(extension methods): typos and improvements, example with braces
2 parents 21f476d + 3b8ae8d commit 0cdf13a

File tree

1 file changed

+23
-18
lines changed

1 file changed

+23
-18
lines changed

docs/docs/reference/contextual/extension-methods.md

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ circle.circumference
2222
### Translation of Extension Methods
2323

2424
Extension methods are methods that have a parameter clause in front of the defined identifier.
25-
An extension method named `f` translates to method named `extension_f` that takes the leading parameter section as its first argument list.
25+
An extension method named `f` translates to the method named `extension_f` that takes the leading parameter section as its first argument list.
2626
So, the definition of `circumference` above translates to the following method, and can also be invoked as such:
2727

2828
```scala
@@ -76,7 +76,8 @@ extension [T: Numeric](x: T)
7676
```
7777

7878
If an extension method has type parameters, they come immediately after `extension` and are followed by the extended parameter.
79-
When calling a generic extension method, any explicitly given type arguments follow the method name. So the `second` method could be instantiated as follows.
79+
When calling a generic extension method, any explicitly given type arguments follow the method name.
80+
So the `second` method could be instantiated as follows:
8081

8182
```scala
8283
List(1, 2, 3).second[Int]
@@ -91,15 +92,16 @@ extension [T](x: T)(using n: Numeric[T])
9192
def + (y: T): T = n.plus(x, y)
9293
```
9394

94-
**Note**: Type parameters have to be given after the `extension` keyword;
95-
they cannot be given after the `def`. This restriction might be lifted in the future once we support multiple type parameter clauses in a method. By contrast, there can be using clauses in front as well as after the `def`.
95+
**Note**: Type parameters have to be given after the `extension` keyword; they cannot be given after the `def`.
96+
This restriction might be lifted in the future once we support multiple type parameter clauses in a method.
97+
By contrast, using clauses can be defined for the `extension` as well as per `def`.
9698

9799
### Collective Extensions
98100

99101
Sometimes, one wants to define several extension methods that share the same
100102
left-hand parameter type. In this case one can "pull out" the common parameters into
101103
a single extension and enclose all methods in braces or an indented region following a '`:`'.
102-
Example:
104+
Following an example using an indented region:
103105

104106
```scala
105107
extension (ss: Seq[String]):
@@ -111,11 +113,23 @@ extension (ss: Seq[String]):
111113
def longestString: String = longestStrings.head
112114
```
113115

116+
The same can be written with braces as follows (note that indented regions can still be used inside braces):
117+
```scala
118+
extension (ss: Seq[String]) {
119+
120+
def longestStrings: Seq[String] =
121+
val maxLength = ss.map(_.length).max
122+
ss.filter(_.length == maxLength)
123+
124+
def longestString: String = longestStrings.head
125+
}
126+
```
127+
114128
Note the right-hand side of `longestString`: it calls `longestStrings` directly, implicitly
115129
assuming the common extended value `ss` as receiver.
116130

117131
Collective extensions like these are a shorthand for individual extensions
118-
where each method is defined separately. For instance, the first extension above expands to
132+
where each method is defined separately. For instance, the first extension above expands to:
119133

120134
```scala
121135
extension (ss: Seq[String])
@@ -127,16 +141,6 @@ extension (ss: Seq[String])
127141
def longestString: String = ss.longestStrings.head
128142
```
129143

130-
Collective extensions also can take type parameters and have using clauses. Example
131-
132-
```scala
133-
extension [T](xs: List[T])(using Ordering[T]):
134-
def smallest(n: Int): List[T] = xs.sorted.take(n)
135-
def smallestIndices(n: Int): List[Int] =
136-
val limit = smallest(n).max
137-
xs.zipWithIndex.collect { case (x, i) if x <= limit => i }
138-
```
139-
140144
### Translation of Calls to Extension Methods
141145

142146
To convert a reference to an extension method, the compiler has to know about the extension
@@ -211,7 +215,8 @@ List(1, 2) < List(3)
211215

212216
The precise rules for resolving a selection to an extension method are as follows.
213217

214-
Assume a selection `e.m[Ts]` where `m` is not a member of `e`, where the type arguments `[Ts]` are optional, and where `T` is the expected type. The following two rewritings are tried in order:
218+
Assume a selection `e.m[Ts]` where `m` is not a member of `e`, where the type arguments `[Ts]` are optional, and where `T` is the expected type.
219+
The following two rewritings are tried in order:
215220

216221
1. The selection is rewritten to `extension_m[Ts](e)`.
217222
2. If the first rewriting does not typecheck with expected type `T`,
@@ -252,7 +257,7 @@ def extension_position(s: String)(ch: Char, n: Int): Int =
252257
1. To avoid confusion, names of normal methods are not allowed to start with `extension_`.
253258

254259
2. A named import such as `import a.m` of an extension method in `a` will make `m` only available as an extension method.
255-
To access it under `extension_m` that name as to be imported separately. Example:
260+
To access it under `extension_m` that name has to be imported separately. Example:
256261

257262
```scala
258263
object DoubleOps:

0 commit comments

Comments
 (0)