Skip to content

Commit 379bc06

Browse files
committed
Reorganize docs to consolidate all implicit changes
1 parent ae2f23c commit 379bc06

17 files changed

+1034
-342
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,8 +2018,8 @@ object Parsers {
20182018
/** ClsParamClause ::= [nl | ‘with’] `(' [FunArgMods] [ClsParams] ')'
20192019
* ClsParams ::= ClsParam {`' ClsParam}
20202020
* ClsParam ::= {Annotation} [{Modifier} (`val' | `var') | `inline'] Param
2021-
* DefParamClause ::= [nl] `(' [FunArgMods] [DefParams] ')' | InstParamClause
2022-
* InstParamClause ::= ‘given’ (‘(’ DefParams ‘)’ | ContextTypes)
2021+
* DefParamClause ::= [nl] `(' [FunArgMods] [DefParams] ')' | InferParamClause
2022+
* InferParamClause ::= ‘given’ (‘(’ DefParams ‘)’ | ContextTypes)
20232023
* ContextTypes ::= RefinedType {`,' RefinedType}
20242024
* DefParams ::= DefParam {`,' DefParam}
20252025
* DefParam ::= {Annotation} [`inline'] Param
@@ -2112,7 +2112,7 @@ object Parsers {
21122112

21132113
/** ClsParamClauses ::= {ClsParamClause}
21142114
* DefParamClauses ::= {DefParamClause}
2115-
* InstParamClauses ::= {InstParamClause}
2115+
* InferParamClauses ::= {InferParamClause}
21162116
*
21172117
* @return The parameter definitions
21182118
*/
@@ -2536,7 +2536,7 @@ object Parsers {
25362536
}
25372537

25382538
/** InstanceDef ::= [id] InstanceParams InstanceBody
2539-
* InstanceParams ::= [DefTypeParamClause] {InstParamClause}
2539+
* InstanceParams ::= [DefTypeParamClause] {InferParamClause}
25402540
* InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
25412541
* | ‘of’ Type ‘=’ Expr
25422542
*/

docs/docs/internals/syntax.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ SimpleType ::= SimpleType TypeArgs
156156
| [‘-’ | ‘+’ | ‘~’ | ‘!’] StableId PrefixOp(expr, op)
157157
| Path ‘.’ ‘type’ SingletonTypeTree(p)
158158
| ‘(’ ArgTypes ‘)’ Tuple(ts)
159-
| ‘_’ TypeBounds
159+
| ‘_’ SubtypeBounds
160160
| Refinement RefinedTypeTree(EmptyTree, refinement)
161161
| SimpleLiteral SingletonTypeTree(l)
162162
ArgTypes ::= Type {‘,’ Type}
@@ -169,8 +169,8 @@ TypeArgs ::= ‘[’ ArgTypes ‘]’
169169
NamedTypeArg ::= id ‘=’ Type NamedArg(id, t)
170170
NamedTypeArgs ::= ‘[’ NamedTypeArg {‘,’ NamedTypeArg} ‘]’ nts
171171
Refinement ::= ‘{’ [RefineDcl] {semi [RefineDcl]} ‘}’ ds
172-
TypeBounds ::= [‘>:’ Type] [‘<:’ Type] | INT TypeBoundsTree(lo, hi)
173-
TypeParamBounds ::= TypeBounds {‘<%’ Type} {‘:’ Type} ContextBounds(typeBounds, tps)
172+
SubtypeBounds ::= [‘>:’ Type] [‘<:’ Type] | INT TypeBoundsTree(lo, hi)
173+
TypeParamBounds ::= SubtypeBounds {‘<%’ Type} {‘:’ Type} ContextBounds(typeBounds, tps)
174174
```
175175

176176
### Expressions
@@ -281,11 +281,11 @@ DefTypeParamClause::= ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
281281
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds
282282
283283
TypTypeParamClause::= ‘[’ TypTypeParam {‘,’ TypTypeParam} ‘]’
284-
TypTypeParam ::= {Annotation} id [HkTypeParamClause] TypeBounds
284+
TypTypeParam ::= {Annotation} id [HkTypeParamClause] SubtypeBounds
285285
286286
HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’
287287
HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (Id[HkTypeParamClause] | ‘_’)
288-
TypeBounds
288+
SubtypeBounds
289289
290290
ClsParamClauses ::= {ClsParamClause}
291291
ClsParamClause ::= [nl] ‘(’ [[FunArgMods] ClsParams] ‘)’
@@ -297,8 +297,8 @@ Param ::= id ‘:’ ParamType [‘=’ Expr]
297297
| INT
298298
299299
DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [FunArgMods] DefParams ‘)’]
300-
DefParamClause ::= [nl] ‘(’ [DefParams] ‘)’ | InstParamClause
301-
InstParamClause ::= ‘given’ (‘(’ [DefParams] ‘)’ | ContextTypes)
300+
DefParamClause ::= [nl] ‘(’ [DefParams] ‘)’ | InferParamClause
301+
InferParamClause ::= ‘given’ (‘(’ [DefParams] ‘)’ | ContextTypes)
302302
DefParams ::= DefParam {‘,’ DefParam}
303303
DefParam ::= {Annotation} [‘inline’] Param ValDef(mods, id, tpe, expr) -- point of mods at id.
304304
ContextTypes ::= RefinedType {‘,’ RefinedType}
@@ -346,7 +346,7 @@ VarDcl ::= ids ‘:’ Type
346346
DefDcl ::= DefSig [‘:’ Type] DefDef(_, name, tparams, vparamss, tpe, EmptyTree)
347347
DefSig ::= ‘(’ DefParam ‘)’ [nl] id
348348
[DefTypeParamClause] DefParamClauses
349-
TypeDcl ::= id [TypeParamClause] (TypeBounds | ‘=’ Type) TypeDefTree(_, name, tparams, bounds)
349+
TypeDcl ::= id [TypeParamClause] (SubtypeBounds | ‘=’ Type) TypeDefTree(_, name, tparams, bounds)
350350
| id [TypeParamClause] <: Type = MatchType
351351
352352
Def ::= ‘val’ PatDef
@@ -374,7 +374,7 @@ ConstrMods ::= {Annotation} [AccessModifier]
374374
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
375375
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
376376
InstanceDef ::= [id] InstanceParams InstanceBody
377-
InstanceParams ::= [DefTypeParamClause] {InstParamClause}
377+
InstanceParams ::= [DefTypeParamClause] {InferParamClause}
378378
InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] [TemplateBody]
379379
| ‘of’ Type ‘=’ Expr
380380
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
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 a common pattern of implicit parameters. For example, the `maximum` function of the last section could also have been written like this:
9+
```scala
10+
def maximum[T: Ord](xs: List[T]): T = xs.reduceLeft(max)
11+
```
12+
A bound `: C` on a type parameter `T` of a method or class indicates an inferred parameter `given C[T]`. The inferred parameter(s) generated from context bounds come last in the definition of the containing method or class. E.g.,
13+
```
14+
def f[T: C1 : C2, U: C3](x: T) given (y: U, z: V): R
15+
```
16+
would expand to
17+
```
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+
```
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: 62 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,76 @@
11
---
22
layout: doc-page
3-
title: "Inferred Parameters and Arguments"
3+
title: "Inferable Parameters and Arguments"
44
---
55

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
7-
```scala
8-
def f(a: A)(implicit b: B)
6+
Functional programming tends to express most dependencies as simple functions parameterization.
7+
This is clean and powerful, but it sometimes leads to functions that take many parameters and
8+
call trees where the same value is passed over and over again in long call chains to many
9+
functions. Inferable parameters can help here since they enable the compiler to synthesize
10+
repetitive arguments instead of the programmer having to write them explicitly.
11+
12+
For example, given the [instance definitions](./instance-definitions.md) defined previously,
13+
a maximum function that works for any arguments for which an ordering exists can be defined as follows:
914
```
10-
is now expressed as
11-
```scala
12-
def f(a: A) given (b: B)
15+
def max[T](x: T, y: T) given (ord: Ord[T]): T =
16+
if (ord.compare(x, y) < 1) y else x
1317
```
14-
or, leaving out the parameter name,
15-
```scala
16-
def f(a: A) given B
18+
Here, `ord` is an _inferable parameter_. Inferable parameters are introduced with a `given` clause. Here is an example application of `max`:
19+
```
20+
max(2, 3) given IntOrd
1721
```
18-
Implicit parameters defined with the new syntax are also called _context parameters_.
19-
They come with a matching syntax for applications: explicit arguments for context parameters are also written after a `given`.
22+
The `given IntOrd` part provides the `IntOrd` instance as an argument for the `ord` parameter. But the point of inferable parameters is that this argument can also be left out (and usually is):
23+
```
24+
max(2, 3)
25+
```
26+
This is equally valid, and is completed by the compiler to the previous application.
2027

21-
The following example shows shows three methods that each have a context parameter for `Ord[T]`.
22-
```scala
28+
## Anonymous Inferred Parameters
29+
30+
In many situations, the name of an inferable parameter of a method need not be
31+
mentioned explicitly at all, since it is only used in synthesized arguments for
32+
other inferable parameters. In that case one can avoid defining a parameter name
33+
and just provide its type. Example:
34+
```
2335
def maximum[T](xs: List[T]) given Ord[T]: T =
24-
xs.reduceLeft((x, y) => if (x < y) y else x)
36+
xs.reduceLeft(max)
37+
```
38+
`maximum` takes an inferable parameter of type `Ord` only to pass it on as an
39+
inferred argument to `max`. The name of the parameter is left out.
40+
41+
Generally, inferable parameters may be given either as a parameter list `(p_1: T_1, ..., p_n: T_n)`
42+
or as a sequence of types, separated by commas. To distinguish the two, a leading
43+
`(` always indicates a parameter list.
44+
45+
## Synthesizing Complex Inferred Arguments
2546

47+
Here are two other methods that have an inferable parameter of type `Ord[T]`:
48+
```scala
2649
def descending[T] given (asc: Ord[T]): Ord[T] = new Ord[T] {
27-
def (x: T) compareTo (y: T) = asc.compareTo(y)(x)
50+
def compare(x: T, y: T) = asc.compare(y, x)
2851
}
2952

3053
def minimum[T](xs: List[T]) given Ord[T] =
3154
maximum(xs) given descending
3255
```
3356
The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`.
34-
But usually, explicit arguments for context parameters are be left out. For instance,
57+
But usually, explicit arguments for inferable parameters are be left out. For instance,
3558
given `xs: List[Int]`, the following calls are all possible (and they all normalize to the last one:)
3659
```scala
37-
maximum(xs)
60+
minimum(xs)
3861
maximum(xs) given descending
39-
maximum(xs) given (descending given IntOrd)
62+
maximum(xs) given (descending given ListOrd)
63+
maximum(xs) given (descending given (ListOrd given InOrd))
4064
```
41-
Arguments for context parameters must use the `given` syntax. So the expression `maximum(xs)(descending)` would produce a type error.
65+
In summary, the argument passed in the definition of minimum is constructed
66+
from the `descending` function applied to the argument `ListOrd`, which is
67+
in turn applied to the argument `IntOrd`.
4268

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:
44-
```scala
45-
def f given (x: A, y: B)
46-
f given (a, b)
69+
## Mixing Inferable And Normal Parameters
4770

48-
def g given (xy: (A, B))
49-
g given ((a, b))
50-
```
51-
Unlike existing implicit parameters, context parameters can be freely mixed with normal parameter lists.
52-
A context parameter may be followed by a normal parameter and _vice versa_. There can be several context parameter
53-
lists in a definition. Example:
71+
Inferable parameters can be freely mixed with normal parameter lists.
72+
An inferable parameter may be followed by a normal parameter and _vice versa_.
73+
There can be several inferable parameter lists in a definition. Example:
5474
```scala
5575
def f given (u: Universe) (x: u.T) given Context = ...
5676

@@ -64,15 +84,17 @@ f("abc")
6484
f("abc") given ctx
6585
(f given global)("abc") given ctx
6686
```
67-
Context parameters may be given either as a normal parameter list `(...)`
68-
or as a sequence of types. To distinguish the two, a leading `(` always indicates a parameter list.
6987

70-
## Summoning an Instance
88+
## Summmoning an Inferred Instance
7189

72-
A method `summon` in `Predef` returns the inferred value for a given type, analogously to what `implicitly[T]` did. The only difference between the two is that
73-
`summon` takes a context parameter, where `implicitly` took an old-style implicit parameter:
90+
A method `infer` in `Predef` creates an instance value for a given type. For example,
91+
the instance value for `Ord[List[Int]]` is generated by
92+
```
93+
infer[Ord[List[Int]]]
94+
```
95+
The `infer` method is simply defined as the identity function with an inferable parameter.
7496
```scala
75-
def summon[T] with (x: T) = x
97+
def infer[T] given (x: T) = x
7698
```
7799

78100
## Syntax
@@ -82,7 +104,10 @@ Here is the new syntax of parameters and arguments seen as a delta from the [sta
82104
ClsParamClause ::= ...
83105
| ‘given’ (‘(’ [ClsParams] ‘)’ | ContextTypes)
84106
DefParamClause ::= ...
85-
| InstParamClause
107+
| InferParamClause
108+
InferParamClause ::= ‘given’ (‘(’ DefParams ‘)’ | ContextTypes)
109+
ContextTypes ::= RefinedType {‘,’ RefinedType}
110+
86111
InfixExpr ::= ...
87112
| InfixExpr ‘given’ (InfixExpr | ParArgumentExprs)
88113
```

0 commit comments

Comments
 (0)