Skip to content

Commit 541ec60

Browse files
committed
Document new changes
1 parent 93ff8f1 commit 541ec60

File tree

2 files changed

+100
-2
lines changed

2 files changed

+100
-2
lines changed

docs/docs/reference/contextual/using-clauses.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ Here is the new syntax of parameters and arguments seen as a delta from the [sta
146146

147147
```
148148
ClsParamClause ::= ... | UsingClsParamClause
149-
DefParamClauses ::= ... | UsingParamClause
149+
DefParamClause ::= ... | UsingParamClause
150150
UsingClsParamClause ::= ‘(’ ‘using’ (ClsParams | Types) ‘)’
151-
UsingParamClause ::= ‘(’ ‘using’ (DefParams | Types) ‘)’
151+
UsingParamClause ::= ‘(’ ‘using’ (DefTermParams | Types) ‘)’
152152
ParArgumentExprs ::= ... | ‘(’ ‘using’ ExprsInParens ‘)’
153153
```
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
layout: doc-page
3+
title: "Generalized Method Syntax"
4+
movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/generalized-method-syntax.html
5+
---
6+
7+
The inclusion of using clauses is not the only way in which methods have been updated, type parameter clauses are now allowed in any number and at any position.
8+
9+
## Syntax Changes
10+
11+
### In Scala 2
12+
13+
The old syntax only allowed zero or one type parameter clause, followed by any number of term clauses, optionnally followed by an implicit clause:
14+
15+
```scala
16+
def foo[T, U](x: T)(y: U)(z: Int, s: String)(a: Array[T])(implicit List[U])
17+
```
18+
19+
### In Scala 3
20+
21+
The new syntax allows any number of type, term and using clause, in any order, optionnaly followed by an implicit clause:
22+
(do note however that [implicit clause are discouraged, in favor of using clauses](https://docs.scala-lang.org/scala3/reference/contextual/relationship-implicits.html))
23+
24+
```scala
25+
def foo[T, U](x: T)(y: U)[V](z: V, s: String)[A](a: Array[A])(implicit List[U])
26+
```
27+
28+
### Unchanged
29+
30+
Class definitions and type declarations are unaffected, there can only be up to one type clause, in leading posion.
31+
32+
## Motivation
33+
34+
The new syntax is a powerful but natural extension of the old one, it allows new design patterns while staying intuitive and legible.
35+
36+
### Dependent Type Clauses
37+
38+
As type clauses can come after term clauses, it is now possible to have type parameters depend on term parameters:
39+
40+
```scala
41+
trait Key { type Value }
42+
trait DB {
43+
def get(k: Key): Option[k.Value] // dependent return type
44+
def getOrElse(k: Key)[V >: k.Value](default: V): V // dependent type parameter
45+
}
46+
```
47+
48+
Note that simply replacing `V` by `k.Value` would not be equivalent. For example, if `k.Value` is `Int`, the above allows:
49+
`getOrElse(k)[Number](0.1)`, which returns a `Number`.
50+
51+
### Partial Inference
52+
53+
It is now possible to only infer some of the type parameters, this reduces boilerplate at the use site:
54+
```scala
55+
trait StaticSizeList[S <: Int & Singleton, T]
56+
def filled[S <: Int & Singleton][T](x: T): StaticSizeList[S,T] = ???
57+
val helloes = filled[4]("Hello!") // S=4, and T is inferred
58+
```
59+
60+
## Details
61+
62+
### Application
63+
64+
Method application is unchanged, in cases where multiple type clauses are expected but not all are passed, the leftmost ones are inferred.
65+
66+
In particular, the following does not type check, even though the argument `Char` is only valid for `C`:
67+
```scala
68+
def triple[A <: Int][B <: String][C <: Char](a: A, b: B, c: C) = ???
69+
triple[Int][Char](0,"",'c') // error: Char does not conform to upperbound String
70+
```
71+
72+
### Extension Methods
73+
74+
Naturally extension methods follow the same syntax, so the following is valid:
75+
```scala
76+
extension [T](l1: List[T])
77+
def zipWith[U](l2: List[U])[V](l3: List[V]): List[(T,U,V)]
78+
```
79+
80+
### Formal syntax
81+
82+
```
83+
DefDcl ::= DefSig ‘:’ Type
84+
DefDef ::= DefSig [‘:’ Type] ‘=’ Expr
85+
DefSig ::= id [DefParamClauses] [DefImplicitClause]
86+
DefParamClauses ::= DefParamClause { DefParamClause }
87+
DefParamClause ::= DefTypeParamClause
88+
| DefTermParamClause
89+
| UsingParamClause
90+
DefTypeParamClause::= [nl] ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
91+
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds
92+
DefTermParamClause::= [nl] ‘(’ [DefTermParams] ‘)’
93+
UsingParamClause ::= [nl] ‘(’ ‘using’ (DefTermParams | FunArgTypes) ‘)’
94+
DefImplicitClause ::= [nl] ‘(’ ‘implicit’ DefTermParams ‘)’
95+
DefTermParams ::= DefTermParam {‘,’ DefTermParam}
96+
DefTermParam ::= {Annotation} [‘inline’] Param
97+
Param ::= id ‘:’ ParamType [‘=’ Expr]
98+
```

0 commit comments

Comments
 (0)