Skip to content

Commit 5ea1ee6

Browse files
committed
Docs reorg
Have (mostly) standard reference pages describing the new features. The old proposal-style content is kept in the `discussion` subdirectory. Changes compared to previous version - anonymous context parameter syntax - implicit as a modifier - Conversion trait instead of ImplicitConversion
1 parent 6394b6f commit 5ea1ee6

12 files changed

+635
-216
lines changed

docs/docs/internals/syntax.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,17 +289,20 @@ HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (Id[HkTypeParamClause] |
289289
TypeBounds
290290
291291
ClsParamClauses ::= {ClsParamClause}
292-
ClsParamClause ::= [nl | ‘with’] ‘(’ [[FunArgMods] ClsParams] ‘)’
292+
ClsParamClause ::= [nl] ‘(’ [[FunArgMods] ClsParams] ‘)’
293+
| ‘with’ (‘(’ ([[FunArgMods] ClsParams] ‘)’ | ParamTypes)
293294
ClsParams ::= ClsParam {‘,’ ClsParam}
294295
ClsParam ::= {Annotation} ValDef(mods, id, tpe, expr) -- point of mods on val/var
295296
[{Modifier} (‘val’ | ‘var’) | ‘inline’] Param
296297
Param ::= id ‘:’ ParamType [‘=’ Expr]
297298
| INT
298299
299300
DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [FunArgMods] DefParams ‘)’]
300-
DefParamClause ::= [nl | ‘with’] ‘(’ [DefParams] ‘)’
301+
DefParamClause ::= [nl] ‘(’ [DefParams] ‘)’ | InstParamClause
302+
InstParamClause ::= ‘with’ (‘(’ [DefParams] ‘)’ | ParamTypes)
301303
DefParams ::= DefParam {‘,’ DefParam}
302304
DefParam ::= {Annotation} [‘inline’] Param ValDef(mods, id, tpe, expr) -- point of mods at id.
305+
ParamTypes ::= InfixType {‘,’ InfixType}
303306
```
304307

305308
### Bindings and Imports
@@ -369,10 +372,7 @@ ConstrMods ::= {Annotation} [AccessModifier]
369372
ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor
370373
EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template)
371374
InstanceDef ::= [id] InstanceParams [‘of’ ConstrApps] [TemplateBody]
372-
| id InstanceParams ‘:’ Type ‘=’ Expr
373-
| id ‘:’ ‘=>’ Type ‘=’ Expr
374-
| id ‘=’ Expr
375-
InstanceParams ::= [DefTypeParamClause] {‘with’ ‘(’ [DefParams] ‘)'}
375+
InstanceParams ::= [DefTypeParamClause] {InstParamClause}
376376
Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats)
377377
InheritClauses ::= [‘extends’ ConstrApps] [‘derives’ QualId {‘,’ QualId}]
378378
ConstrApps ::= ConstrApp {‘with’ ConstrApp}

docs/docs/reference/instances/context-params.md

Lines changed: 24 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,36 @@ layout: doc-page
33
title: "Context Parameters and Arguments"
44
---
55

6-
This page presents new syntax for defining implicit parameters that aligns definition and call syntax. In both cases, the implicit parameter or argument now follows a `with` connective.
7-
On the definition side, the old syntax
6+
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
88
```scala
99
def f(a: A)(implicit b: B)
1010
```
1111
is now expressed as
1212
```scala
1313
def f(a: A) with (b: B)
1414
```
15+
or, leaving out the parameter name,
16+
```scala
17+
def f(a: A) with B
18+
```
1519
Implicit parameters defined with the new syntax are also called _context parameters_.
1620
They come with a matching syntax for applications: explicit arguments for context parameters are also given after a `with`.
1721

1822
The following example shows shows three methods that each have a context parameter for `Ord[T]`.
1923
```scala
20-
def maximum[T](xs: List[T]) with (cmp: Ord[T]): T =
24+
def maximum[T](xs: List[T]) with Ord[T]: T =
2125
xs.reduceLeft((x, y) => if (x < y) y else x)
2226

2327
def descending[T] with (asc: Ord[T]): Ord[T] = new Ord[T] {
2428
def (x: T) compareTo (y: T) = asc.compareTo(y)(x)
2529
}
2630

27-
def minimum[T](xs: List[T]) with (cmp: Ord[T]) =
31+
def minimum[T](xs: List[T]) with Ord[T] =
2832
maximum(xs) with descending
2933
```
30-
The `minimum` method's right hand side defines the explicit argument `descending`.
31-
Explicit arguments for context parameters can be left out. For instance,
34+
The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`.
35+
But usually, explicit arguments for context parameters are be left out. For instance,
3236
given `xs: List[Int]`, the following calls are all possible (and they all normalize to the last one:)
3337
```scala
3438
maximum(xs)
@@ -45,77 +49,31 @@ f with (a, b)
4549
def g with (xy: (A, B))
4650
g with ((a, b))
4751
```
48-
49-
## Implicit Function Types and Closures
50-
51-
Implicit function types are expressed using the new reserved operator `|=>`. Examples:
52+
Unlike existing implicit parameters, context parameters can be freely mixed with normal parameter lists.
53+
A context parameter may be followed by a normal parameter and _vice versa_. There can be several context parameter
54+
lists in a definition. Example:
5255
```scala
53-
Context |=> T
54-
A |=> B |=> T
55-
(A, B) |=> T
56-
(x: A, y: B) |=> T
57-
```
58-
The `|=>` syntax was chosen for its resemblance with a turnstile symbol `|-` which signifies context dependencies.
56+
def f with (u: Universe) (x: u.T) with Context = ...
5957

60-
The old syntax `implicit A => B` is no longer available.
61-
Implicit function types are applied using `with`:
62-
```scala
63-
val f: A |=> B
64-
val a: A
65-
f with a // OK
66-
f(a) // error: `f` does not take parameters
58+
instance global for Universe { type T = String ... }
59+
instance ctx for Context { ... }
6760
```
68-
Since application of regular function types and implicit function types different, implicit function types are no longer subtypes of regular function types.
69-
70-
The `|=>` syntax can also be used for closures. It turns the parameter bindings into implicit
71-
parameters and makes the closure's type an implicit function type
61+
Then the following calls are all valid (and normalize to the last one)
7262
```scala
73-
case class Context(value: String)
74-
val f1: Context |=> String = ctx |=> ctx.value
75-
val f2: Context |=> String = (ctx: Context) |=> ctx.value
76-
val f3: (A, B) |=> T = (a: A, b: B) |=> t
63+
f("abc")
64+
(f with global)("abc")
65+
f("abc") with ctx
66+
(f with global)("abc") with ctx
7767
```
78-
The old syntax `implicit (a: A) => B` now creates a closure of a regular function type `A => B` instead of an implicit function type `A |=> B`. This matches the types of implicit closures in Scala 2.x.
79-
80-
## Example
8168

82-
Implementing postconditions via `ensuring`:
83-
```scala
84-
object PostConditions {
85-
opaque type WrappedResult[T] = T
86-
87-
private instance WrappedResult {
88-
def apply[T](x: T): WrappedResult[T] = x
89-
def (x: WrappedResult[T]) unwrap[T]: T = x
90-
}
91-
92-
def result[T] with (wrapped: WrappedResult[T]): T = wrapped.unwrap
93-
94-
instance {
95-
def (x: T) ensuring[T] (condition: WrappedResult[T] |=> Boolean): T = {
96-
assert(condition with WrappedResult(x))
97-
x
98-
}
99-
}
100-
}
101-
102-
object Test {
103-
import PostConditions._
104-
val s = List(1, 2, 3).sum.ensuring(result == 6)
105-
}
106-
```
10769
## Syntax
10870

109-
Here is the new syntax of parameters, arguments, and implicit function types seen as a delta from the [standard context free syntax of Scala 3](http://dotty.epfl.ch/docs/internals/syntax.html).
71+
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).
11072
```
11173
ClsParamClause ::= ...
112-
| ‘with’ ‘(’ [ClsParams] ‘)’
74+
| ‘with’ (‘(’ [ClsParams] ‘)’ | ParamTypes)
11375
DefParamClause ::= ...
114-
| ‘with’ ‘(’ [DefParams] ‘)’
115-
Type ::= ...
116-
| [‘erased’] FunArgTypes ‘|=>’ Type
117-
Expr ::= ...
118-
| [‘erased’] FunParams ‘|=>’ Expr
76+
| InstParamClause
11977
InfixExpr ::= ...
12078
| InfixExpr ‘with’ (InfixExpr | ParArgumentExprs)
12179
```
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
---
2+
layout: doc-page
3+
title: "Context Parameters and Arguments"
4+
---
5+
6+
This page presents new syntax for defining implicit parameters that aligns definition and call syntax. In both cases, the implicit parameter or argument now follows a `with` connective.
7+
On the definition side, the old syntax
8+
```scala
9+
def f(a: A)(implicit b: B)
10+
```
11+
is now expressed as
12+
```scala
13+
def f(a: A) with (b: B)
14+
```
15+
Implicit parameters defined with the new syntax are also called _context parameters_.
16+
They come with a matching syntax for applications: explicit arguments for context parameters are also given after a `with`.
17+
18+
The following example shows shows three methods that each have a context parameter for `Ord[T]`.
19+
```scala
20+
def maximum[T](xs: List[T]) with (cmp: Ord[T]): T =
21+
xs.reduceLeft((x, y) => if (x < y) y else x)
22+
23+
def descending[T] with (asc: Ord[T]): Ord[T] = new Ord[T] {
24+
def (x: T) compareTo (y: T) = asc.compareTo(y)(x)
25+
}
26+
27+
def minimum[T](xs: List[T]) with (cmp: Ord[T]) =
28+
maximum(xs) with descending
29+
```
30+
The `minimum` method's right hand side defines the explicit argument `descending`.
31+
Explicit arguments for context parameters can be left out. For instance,
32+
given `xs: List[Int]`, the following calls are all possible (and they all normalize to the last one:)
33+
```scala
34+
maximum(xs)
35+
maximum(xs) with descending
36+
maximum(xs) with (descending with IntOrd)
37+
```
38+
Arguments for context parameters must be given using the `with` syntax. So the expression `maximum(xs)(descending)` would give a type error.
39+
40+
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:
41+
```scala
42+
def f with (x: A, y: B)
43+
f with (a, b)
44+
45+
def g with (xy: (A, B))
46+
g with ((a, b))
47+
```
48+
49+
## Implicit Function Types and Closures
50+
51+
Implicit function types are expressed using the new reserved operator `|=>`. Examples:
52+
```scala
53+
Context |=> T
54+
A |=> B |=> T
55+
(A, B) |=> T
56+
(x: A, y: B) |=> T
57+
```
58+
The `|=>` syntax was chosen for its resemblance with a turnstile symbol `|-` which signifies context dependencies.
59+
60+
The old syntax `implicit A => B` is no longer available.
61+
Implicit function types are applied using `with`:
62+
```scala
63+
val f: A |=> B
64+
val a: A
65+
f with a // OK
66+
f(a) // error: `f` does not take parameters
67+
```
68+
Since application of regular function types and implicit function types different, implicit function types are no longer subtypes of regular function types.
69+
70+
The `|=>` syntax can also be used for closures. It turns the parameter bindings into implicit
71+
parameters and makes the closure's type an implicit function type
72+
```scala
73+
case class Context(value: String)
74+
val f1: Context |=> String = ctx |=> ctx.value
75+
val f2: Context |=> String = (ctx: Context) |=> ctx.value
76+
val f3: (A, B) |=> T = (a: A, b: B) |=> t
77+
```
78+
The old syntax `implicit (a: A) => B` now creates a closure of a regular function type `A => B` instead of an implicit function type `A |=> B`. This matches the types of implicit closures in Scala 2.x.
79+
80+
## Example
81+
82+
Implementing postconditions via `ensuring`:
83+
```scala
84+
object PostConditions {
85+
opaque type WrappedResult[T] = T
86+
87+
private instance WrappedResult {
88+
def apply[T](x: T): WrappedResult[T] = x
89+
def (x: WrappedResult[T]) unwrap[T]: T = x
90+
}
91+
92+
def result[T] with (wrapped: WrappedResult[T]): T = wrapped.unwrap
93+
94+
instance {
95+
def (x: T) ensuring[T] (condition: WrappedResult[T] |=> Boolean): T = {
96+
assert(condition with WrappedResult(x))
97+
x
98+
}
99+
}
100+
}
101+
102+
object Test {
103+
import PostConditions._
104+
val s = List(1, 2, 3).sum.ensuring(result == 6)
105+
}
106+
```
107+
## Syntax
108+
109+
Here is the new syntax of parameters, arguments, and implicit function types seen as a delta from the [standard context free syntax of Scala 3](http://dotty.epfl.ch/docs/internals/syntax.html).
110+
```
111+
ClsParamClause ::= ...
112+
| ‘with’ ‘(’ [ClsParams] ‘)’
113+
DefParamClause ::= ...
114+
| ‘with’ ‘(’ [DefParams] ‘)’
115+
Type ::= ...
116+
| [‘erased’] FunArgTypes ‘|=>’ Type
117+
Expr ::= ...
118+
| [‘erased’] FunParams ‘|=>’ Expr
119+
InfixExpr ::= ...
120+
| InfixExpr ‘with’ (InfixExpr | ParArgumentExprs)
121+
```

0 commit comments

Comments
 (0)