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
Context parameters are the name of a new syntax for implicit parameters that aligns definition and call syntax. Parameter definitions
7
-
and method arguments both follow a `with` connective. On the definition side, the old syntax
6
+
A new syntax for implicit parameters aligns definition and call syntax. Parameter definitions and method arguments both follow a `given` keyword. On the definition side, the old syntax
8
7
```scala
9
8
deff(a: A)(implicitb: B)
10
9
```
11
10
is now expressed as
12
11
```scala
13
-
deff(a: A) with (b: B)
12
+
deff(a: A) given (b: B)
14
13
```
15
14
or, leaving out the parameter name,
16
15
```scala
17
-
deff(a: A) withB
16
+
deff(a: A) givenB
18
17
```
19
18
Implicit parameters defined with the new syntax are also called _context parameters_.
20
-
They come with a matching syntax for applications: explicit arguments for context parameters are also given after a `with`.
19
+
They come with a matching syntax for applications: explicit arguments for context parameters are also written after a `given`.
21
20
22
21
The following example shows shows three methods that each have a context parameter for `Ord[T]`.
23
22
```scala
24
-
defmaximum[T](xs: List[T]) withOrd[T]:T=
23
+
defmaximum[T](xs: List[T]) givenOrd[T]:T=
25
24
xs.reduceLeft((x, y) =>if (x < y) y else x)
26
25
27
-
defdescending[T] with (asc: Ord[T]):Ord[T] =newOrd[T] {
26
+
defdescending[T] given (asc: Ord[T]):Ord[T] =newOrd[T] {
28
27
def (x: T) compareTo (y: T) = asc.compareTo(y)(x)
29
28
}
30
29
31
-
defminimum[T](xs: List[T]) withOrd[T] =
32
-
maximum(xs) with descending
30
+
defminimum[T](xs: List[T]) givenOrd[T] =
31
+
maximum(xs) givendescending
33
32
```
34
33
The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`.
35
34
But usually, explicit arguments for context parameters are be left out. For instance,
36
35
given `xs: List[Int]`, the following calls are all possible (and they all normalize to the last one:)
37
36
```scala
38
37
maximum(xs)
39
-
maximum(xs) with descending
40
-
maximum(xs) with (descending withIntOrd)
38
+
maximum(xs) givendescending
39
+
maximum(xs) given (descending givenIntOrd)
41
40
```
42
-
Arguments for context parameters must be given using the `with` syntax. So the expression `maximum(xs)(descending)` would give a type error.
41
+
Arguments for context parameters must use the `given` syntax. So the expression `maximum(xs)(descending)` would produce a type error.
43
42
44
-
The `with` connective is treated like an infix operator with the same precedence as other operators that start with a letter. The expression following a `with` may also be an argument list consisting of several implicit arguments separated by commas. If a tuple should be passed as a single implicit argument (probably an uncommon case), it has to be put in a pair of extra parentheses:
43
+
The `given` connective is treated like an infix operator with the same precedence as other operators that start with a letter. The expression following a `given` may also be an argument list consisting of several implicit arguments separated by commas. If a tuple should be passed as a single implicit argument (probably an uncommon case), it has to be put in a pair of extra parentheses:
45
44
```scala
46
-
deffwith (x: A, y: B)
47
-
f with (a, b)
45
+
deffgiven (x: A, y: B)
46
+
f given (a, b)
48
47
49
-
defgwith (xy: (A, B))
50
-
g with ((a, b))
48
+
defggiven (xy: (A, B))
49
+
g given ((a, b))
51
50
```
52
51
Unlike existing implicit parameters, context parameters can be freely mixed with normal parameter lists.
53
52
A context parameter may be followed by a normal parameter and _vice versa_. There can be several context parameter
Then the following calls are all valid (and normalize to the last one)
62
61
```scala
63
62
f("abc")
64
-
(f with global)("abc")
65
-
f("abc") with ctx
66
-
(f with global)("abc") with ctx
63
+
(f givenglobal)("abc")
64
+
f("abc") givenctx
65
+
(f givenglobal)("abc") givenctx
67
66
```
68
67
Context parameters may be given either as a normal parameter list `(...)`
69
68
or as a sequence of types. To distinguish the two, a leading `(` always indicates a parameter list.
@@ -81,9 +80,9 @@ def summon[T] with (x: T) = x
81
80
Here is the new syntax of parameters and arguments seen as a delta from the [standard context free syntax of Scala 3](http://dotty.epfl.ch/docs/internals/syntax.html).
Copy file name to clipboardExpand all lines: docs/docs/reference/instances/discussion/motivation.md
+13-10Lines changed: 13 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,13 +33,16 @@ Can implicit function types help? Implicit function types allow to abstract over
33
33
34
34
### Alternative Design
35
35
36
-
`implicit` is a modifier that gets attached to various constructs. I.e. we talk about implicit vals, defs, objects, parameters, or arguments. This conveys mechanism rather than intent. What _is_ the intent that we want to convey? Ultimately it's "trade types for terms". The programmer specifies a type and the compiler fills in the term matching that type automatically. So the concept we are after would serve to express definitions that provide the canonical _instances_ for certain types.
37
-
38
-
The next sections elaborate such an alternative design. It consists of three proposals:
39
-
40
-
- A proposal to replace implicit _definitions_ by [instance definitions](./instance-defs.html).
41
-
- A proposal for a [new syntax](./context-params.html) of implicit _parameters_ and their _arguments_.
42
-
- A proposal to [replace all remaining usages](./replacing-implicits.html) of `implicit` in the language.
43
-
44
-
The first two proposals are independent of each other. The last one would work only if the first two are adopted.
45
-
A [discussion page](./discussion.html) summarizes and evaluates the proposal.
36
+
`implicit` is a modifier that gets attached to various constructs.
37
+
I.e. we talk about implicit vals, defs, objects, parameters, or arguments.
38
+
This conveys mechanism rather than intent. What _is_ the intent that we want to convey?
39
+
Ultimately it's "trade types for terms". The programmer specifies a type and the compiler
40
+
fills in the term matching that type automatically. So the concept we are after would
41
+
serve to express definitions that provide the canonical _instances_ for certain types.
42
+
43
+
The next sections elaborate this alternative design. It consists of the following pages:
44
+
45
+
- a proposal to replace implicit _definitions_ by [instance definitions](./instance-defs.md),
46
+
- a proposal for a [new syntax](./context-params.md) of implicit _parameters_ and their _arguments_,
47
+
- updates to the syntax for [implicit function types and closures](./implicit-function-types.md),
48
+
- a new way to express [implicit conversions](./implicit-conversions.md) as instances of a special trait,
Implicit conversions are defined by instances of the `scala.Conversion` class.
7
+
This class is defined in package `scala` as follows:
8
+
```scala
9
+
abstractclassConversion[-T, +U] extends (T=>U)
10
+
```
11
+
For example, here is an implicit conversion from `String` to `Token`:
12
+
```scala
13
+
instance of Conversion[String, Token] {
14
+
defapply(str: String):Token=newKeyWord(str)
15
+
}
16
+
```
17
+
An implicit conversion is applied automatically by the compiler in three situations:
18
+
19
+
1. If an expression `e` has type `T`, and `T` does not conform to the expression's expected type `S`.
20
+
2. In a selection `e.m` with `e` of type `T`, but `T` defines no member `m`.
21
+
3. In an application `e.m(args)` with `e` of type `T`, if ``T` does define
22
+
some member(s) named `m`, but none of these members can be applied to the arguments `args`.
23
+
24
+
In the first case, the compiler looks in the implicit scope for a an instance of
25
+
`scala.Conversion` that maps an argument of type `T` to type `S`. In the second and third
26
+
case, it looks for an instance of `scala.Conversion` that maps an argument of type `T`
27
+
to a type that defines a member `m` which can be applied to `args` if present.
28
+
If such an instance `C` is found, the expression `e` is replaced by `C.apply(e)`.
29
+
30
+
## Examples
31
+
32
+
1. The `Predef` package contains "auto-boxing" conversions that map
33
+
primitive number types to subclasses of `java.lang.Number`. For instance, the
34
+
conversion from `Int` to `java.lang.Integer` can be defined as follows:
35
+
```scala
36
+
instance int2Integer of Conversion[Int, java.lang.Integer] {
37
+
defapply(x: Int) =new java.lang.Integer(x)
38
+
}
39
+
```
40
+
41
+
2. The "magnet" pattern is sometimes used to express many variants of a method. Instead of defining overloaded versions of the method, one can also let the method take one or more arguments of specially defined "magnet" types, into which various argument types can be converted. E.g.
42
+
```scala
43
+
objectCompletions {
44
+
45
+
// The argument "magnet" type
46
+
enumCompletionArg {
47
+
caseError(s: String)
48
+
caseResponse(f: Future[HttpResponse])
49
+
caseStatus(code: Future[StatusCode])
50
+
}
51
+
objectCompletionArg {
52
+
53
+
// conversions defining the possible arguments to pass to `complete`
54
+
// these always come with CompletionArg
55
+
// They can be invoked explicitly, e.g.
56
+
//
57
+
// CompletionArg.from(statusCode)
58
+
59
+
instance from of Conversion[String, CompletionArg] {
60
+
defapply(s: String) =CompletionArg.Error(s)
61
+
}
62
+
instance from of Conversion[Future[HttpResponse], CompletionArg] {
This setup is more complicated than simple overloading of `complete`, but it can still be useful if normal overloading is not available (as in the case above, since we cannot have two overloaded methods that take `Future[...]` arguments), or if normal overloading would lead to a combinatorial explosion of variants.
0 commit comments