Skip to content

Commit 1ffe5f1

Browse files
authored
Merge pull request #7213 from dotty-staging/dual-docs
Revert docs to 0.18 state
2 parents fcbe885 + 6258859 commit 1ffe5f1

36 files changed

+2572
-203
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
layout: doc-page
3+
title: "Context Bounds"
4+
---
5+
6+
## Context Bounds
7+
8+
A context bound is a shorthand for expressing the common pattern of an implicit parameter that depends on a type parameter. Using a context bound, the `maximum` function of the last section can be written like this:
9+
```scala
10+
def maximum[T: Ord](xs: List[T]): T = xs.reduceLeft(max)
11+
```
12+
A bound like `: Ord` on a type parameter `T` of a method or class indicates an implicit parameter `(given Ord[T])`. The implicit parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g.,
13+
```scala
14+
def f[T: C1 : C2, U: C3](x: T)(given y: U, z: V): R
15+
```
16+
would expand to
17+
```scala
18+
def f[T, U](x: T)(given y: U, z: V)(given C1[T], C2[T], C3[U]): R
19+
```
20+
Context bounds can be combined with subtype bounds. If both are present, subtype bounds come first, e.g.
21+
```scala
22+
def g[T <: B : C](x: T): R = ...
23+
```
24+
25+
## Syntax
26+
27+
```
28+
TypeParamBounds ::= [SubtypeBounds] {ContextBound}
29+
ContextBound ::= ‘:’ Type
30+
```
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
layout: doc-page
3+
title: "Implicit Conversions"
4+
---
5+
6+
Implicit conversions are defined by given instances of the `scala.Conversion` class.
7+
This class is defined in package `scala` as follows:
8+
```scala
9+
abstract class Conversion[-T, +U] extends (T => U)
10+
```
11+
For example, here is an implicit conversion from `String` to `Token`:
12+
```scala
13+
given Conversion[String, Token] {
14+
def apply(str: String): Token = new KeyWord(str)
15+
}
16+
```
17+
Using an alias this can be expressed more concisely as:
18+
```scala
19+
given Conversion[String, Token] = new KeyWord(_)
20+
```
21+
An implicit conversion is applied automatically by the compiler in three situations:
22+
23+
1. If an expression `e` has type `T`, and `T` does not conform to the expression's expected type `S`.
24+
2. In a selection `e.m` with `e` of type `T`, but `T` defines no member `m`.
25+
3. In an application `e.m(args)` with `e` of type `T`, if `T` does define
26+
some member(s) named `m`, but none of these members can be applied to the arguments `args`.
27+
28+
In the first case, the compiler looks for a given `scala.Conversion` that maps
29+
an argument of type `T` to type `S`. In the second and third
30+
case, it looks for a given `scala.Conversion` that maps an argument of type `T`
31+
to a type that defines a member `m` which can be applied to `args` if present.
32+
If such an instance `C` is given, the expression `e` is replaced by `C.apply(e)`.
33+
34+
## Examples
35+
36+
1. The `Predef` package contains "auto-boxing" conversions that map
37+
primitive number types to subclasses of `java.lang.Number`. For instance, the
38+
conversion from `Int` to `java.lang.Integer` can be defined as follows:
39+
```scala
40+
given int2Integer: Conversion[Int, java.lang.Integer] =
41+
java.lang.Integer.valueOf(_)
42+
```
43+
44+
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.
45+
```scala
46+
object Completions {
47+
48+
// The argument "magnet" type
49+
enum CompletionArg {
50+
case Error(s: String)
51+
case Response(f: Future[HttpResponse])
52+
case Status(code: Future[StatusCode])
53+
}
54+
object CompletionArg {
55+
56+
// conversions defining the possible arguments to pass to `complete`
57+
// these always come with CompletionArg
58+
// They can be invoked explicitly, e.g.
59+
//
60+
// CompletionArg.fromStatusCode(statusCode)
61+
62+
given fromString : Conversion[String, CompletionArg] = Error(_)
63+
given fromFuture : Conversion[Future[HttpResponse], CompletionArg] = Response(_)
64+
given fromStatusCode : Conversion[Future[StatusCode], CompletionArg] = Status(_)
65+
}
66+
import CompletionArg._
67+
68+
def complete[T](arg: CompletionArg) = arg match {
69+
case Error(s) => ...
70+
case Response(f) => ...
71+
case Status(code) => ...
72+
}
73+
}
74+
```
75+
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.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
---
2+
layout: doc-page
3+
title: "Given Instances"
4+
---
5+
6+
Given instances (or, simply, "givens") define "canonical" values of certain types
7+
that serve for synthesizing arguments to [given clauses](./given-clauses.md). Example:
8+
9+
```scala
10+
trait Ord[T] {
11+
def compare(x: T, y: T): Int
12+
def (x: T) < (y: T) = compare(x, y) < 0
13+
def (x: T) > (y: T) = compare(x, y) > 0
14+
}
15+
16+
given intOrd: Ord[Int] {
17+
def compare(x: Int, y: Int) =
18+
if (x < y) -1 else if (x > y) +1 else 0
19+
}
20+
21+
given listOrd[T](given ord: Ord[T]): Ord[List[T]] {
22+
23+
def compare(xs: List[T], ys: List[T]): Int = (xs, ys) match {
24+
case (Nil, Nil) => 0
25+
case (Nil, _) => -1
26+
case (_, Nil) => +1
27+
case (x :: xs1, y :: ys1) =>
28+
val fst = ord.compare(x, y)
29+
if (fst != 0) fst else xs1.compareTo(ys1)
30+
}
31+
}
32+
```
33+
This code defines a trait `Ord` with two given instances. `intOrd` defines
34+
a given for the type `Ord[Int]` whereas `listOrd[T]` defines givens
35+
for `Ord[List[T]]` for all types `T` that come with a given instance for `Ord[T]` themselves.
36+
The `(given ord: Ord[T])` clause in `listOrd` defines an implicit parameter.
37+
Given clauses are further explained in the [next section](./given-clauses.md).
38+
39+
## Anonymous Given Instances
40+
41+
The name of a given instance can be left out. So the definitions
42+
of the last section can also be expressed like this:
43+
```scala
44+
given Ord[Int] { ... }
45+
given [T](given Ord[T]): Ord[List[T]] { ... }
46+
```
47+
If the name of a given is missing, the compiler will synthesize a name from
48+
the type(s) in the `as` clause.
49+
50+
## Alias Givens
51+
52+
An alias can be used to define a given instance that is equal to some expression. E.g.:
53+
```scala
54+
given global: ExecutionContext = new ForkJoinPool()
55+
```
56+
This creates a given `global` of type `ExecutionContext` that resolves to the right
57+
hand side `new ForkJoinPool()`.
58+
The first time `global` is accessed, a new `ForkJoinPool` is created, which is then
59+
returned for this and all subsequent accesses to `global`.
60+
61+
Alias givens can be anonymous, e.g.
62+
```scala
63+
given Position = enclosingTree.position
64+
given (given outer: Context): Context = outer.withOwner(currentOwner)
65+
```
66+
An alias given can have type parameters and given clauses just like any other given instance, but it can only implement a single type.
67+
68+
## Given Instance Initialization
69+
70+
A given instance without type parameters or given clause is initialized on-demand, the first
71+
time it is accessed. It is not required to ensure safe publication, which means that
72+
different threads might create different instances for the same `given` definition.
73+
If a `given` definition has type parameters or a given clause, a fresh instance is created for each reference.
74+
75+
## Syntax
76+
77+
Here is the new syntax of given instances, seen as a delta from the [standard context free syntax of Scala 3](../../internals/syntax.md).
78+
```
79+
TmplDef ::= ...
80+
| ‘given’ GivenDef
81+
GivenDef ::= [GivenSig (‘:’ | <:)] Type ‘=’ Expr
82+
| [GivenSig ‘:’] [ConstrApp {‘,’ ConstrApp }] [TemplateBody]
83+
GivenSig ::= [id] [DefTypeParamClause] {GivenParamClause}
84+
GivenParamClause ::= ‘(’ ‘given’ (DefParams | GivenTypes) ‘)’
85+
GivenTypes ::= AnnotType {‘,’ AnnotType}
86+
```
87+
The identifier `id` can be omitted only if some types are implemented or the template body defines at least one extension method.

0 commit comments

Comments
 (0)