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
Copy file name to clipboardExpand all lines: docs/docs/reference/contextual/context-bounds.md
+9-4Lines changed: 9 additions & 4 deletions
Original file line number
Diff line number
Diff line change
@@ -3,26 +3,31 @@ layout: doc-page
3
3
title: "Context Bounds"
4
4
---
5
5
6
-
## Context Bounds
7
-
8
6
A context bound is a shorthand for expressing the common pattern of a context parameter that depends on a type parameter. Using a context bound, the `maximum` function of the last section can be written like this:
A bound like `: Ord` on a type parameter `T` of a method or class indicates a context parameter `with Ord[T]`. The context parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g.,
13
+
13
14
```scala
14
15
deff[T:C1:C2, U:C3](x: T)(usingy: U, z: V):R
15
16
```
17
+
16
18
would expand to
19
+
17
20
```scala
18
21
deff[T, U](x: T)(usingy: U, z: V)(usingC1[T], C2[T], C3[U]):R
19
22
```
23
+
20
24
Context bounds can be combined with subtype bounds. If both are present, subtype bounds come first, e.g.
25
+
21
26
```scala
22
27
defg[T<:B:C](x: T):R= ...
23
28
```
24
29
25
-
###Migration
30
+
## Migration
26
31
27
32
To ease migration, context bounds in Dotty map in Scala 3.0 to old-style implicit parameters
28
33
for which arguments can be passed either with a `(using ...)` clause or with a normal application. From Scala 3.1 on, they will map to context parameters instead, as is described above.
@@ -32,7 +37,7 @@ context parameter stemming from a context bound with a normal argument will give
32
37
warning. The warning indicates that a `(using ...)` clause is needed instead. The rewrite can be
Note the swap of the two parameters `x` and `xs` when translating
56
60
the right-associative operator `+:` to an extension method. This is analogous
57
61
to the implementation of right binding operators as normal methods. The Scala
@@ -61,28 +65,30 @@ the two swaps cancel each other out).
61
65
62
66
### Generic Extensions
63
67
64
-
It is also possible to extend generic types by adding type parameters to an extension. For instance:
68
+
It is also possible to extend generic types by adding type parameters to an extension. For instance:
65
69
66
-
```scala
67
-
extension [T](xs: List[T])
68
-
defsecond= xs.tail.head
70
+
```scala
71
+
extension [T](xs: List[T])
72
+
defsecond= xs.tail.head
69
73
70
-
extension [T:Numeric](x: T)
71
-
def+ (y: T):T= summon[Numeric[T]].plus(x, y)
74
+
extension [T:Numeric](x: T)
75
+
def+ (y: T):T= summon[Numeric[T]].plus(x, y)
72
76
```
73
77
74
78
If an extension method has type parameters, they come immediately after `extension` and are followed by the extended parameter.
75
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.
80
+
76
81
```scala
77
-
List(1, 2, 3).second[Int]
82
+
List(1, 2, 3).second[Int]
78
83
```
79
-
Of course, the type argument here would usually be left out since it can be inferred.
80
84
85
+
Of course, the type argument here would usually be left out since it can be inferred.
81
86
82
87
Extensions can also take using clauses. For instance, the `+` extension above could equivalently be written with a using clause:
88
+
83
89
```scala
84
-
extension [T](x: T)(usingn: Numeric[T])
85
-
def- (y: T):T= n.minus(x, y)
90
+
extension [T](x: T)(usingn: Numeric[T])
91
+
def+ (y: T):T= n.plus(x, y)
86
92
```
87
93
88
94
**Note**: Type parameters have to be given after the `extension` keyword;
@@ -94,6 +100,7 @@ Sometimes, one wants to define several extension methods that share the same
94
100
left-hand parameter type. In this case one can "pull out" the common parameters into
95
101
a single extension and enclose all methods in braces or an indented region following a '`:`'.
96
102
Example:
103
+
97
104
```scala
98
105
extension (ss: Seq[String])
99
106
@@ -109,6 +116,7 @@ assuming the common extended value `ss` as receiver.
109
116
110
117
Collective extensions like these are a shorthand for individual extensions
111
118
where each method is defined separately. For instance, the first extension above expands to
119
+
112
120
```scala
113
121
extension (ss: Seq[String])
114
122
deflongestStrings:Seq[String] =
@@ -118,7 +126,9 @@ extension (ss: Seq[String])
118
126
extension (ss: Seq[String])
119
127
deflongestString:String= ss.longestStrings.head
120
128
```
129
+
121
130
Collective extensions also can take type parameters and have using clauses. Example
131
+
122
132
```scala
123
133
extension [T](xs: List[T])(usingOrdering[T])
124
134
defsmallest(n: Int):List[T] = xs.sorted.take(n)
@@ -167,14 +177,17 @@ trait SafeDiv:
167
177
case (Some(d), Some(r)) =>Some((d, r))
168
178
case _ =>None
169
179
```
180
+
170
181
By the second rule, an extension method can be made available by defining a given instance containing it, like this:
182
+
171
183
```scala
172
184
givenops1 as IntOps// brings safeMod into scope
173
185
174
186
1.safeMod(2)
175
187
```
176
188
177
189
By the third and fourth rule, an extension method is available if it is in the implicit scope of the receiver type or in a given instance in that scope. Example:
190
+
178
191
```scala
179
192
classList[T]:
180
193
...
@@ -204,53 +217,58 @@ Assume a selection `e.m[Ts]` where `m` is not a member of `e`, where the type ar
204
217
2. If the first rewriting does not typecheck with expected type `T`,
205
218
and there is an extension method `m` in some eligible object `o`, the selection is rewritten to `o.extension_m[Ts](e)`. An object `o` is _eligible_ if
206
219
207
-
-`o` forms part of the implicit scope of `T`, or
208
-
-`o` is a given instance that is visible at the point of the application, or
209
-
-`o` is a given instance in the implicit scope of `T`.
220
+
-`o` forms part of the implicit scope of `T`, or
221
+
-`o` is a given instance that is visible at the point of the application, or
222
+
-`o` is a given instance in the implicit scope of `T`.
210
223
211
224
This second rewriting is attempted at the time where the compiler also tries an implicit conversion
212
225
from `T` to a type containing `m`. If there is more than one way of rewriting, an ambiguity error results.
213
226
214
227
An extension method can also be used as an identifier by itself. If an identifier `m` does not
215
228
resolve, the identifier is rewritten to:
216
229
217
-
-`x.m` if the identifier appears in an extension with parameter `x`
218
-
-`this.m` otherwise
230
+
-`x.m` if the identifier appears in an extension with parameter `x`
231
+
-`this.m` otherwise
219
232
220
233
and the rewritten term is again tried as an application of an extension method. Example:
234
+
221
235
```scala
222
-
extension (s: String)
223
-
defposition(ch: Char, n: Int):Int=
224
-
if n < s.length && s(n) != ch then position(ch, n +1)
225
-
else n
236
+
extension (s: String)
237
+
defposition(ch: Char, n: Int):Int=
238
+
if n < s.length && s(n) != ch then position(ch, n +1)
239
+
else n
226
240
```
241
+
227
242
The recursive call `position(ch, n + 1)` expands to `s.position(ch, n + 1)` in this case. The whole extension method rewrites to
0 commit comments