Skip to content

Commit

Permalink
Document new changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Sporarum committed Feb 17, 2022
1 parent 93ff8f1 commit 541ec60
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 2 deletions.
4 changes: 2 additions & 2 deletions docs/docs/reference/contextual/using-clauses.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ Here is the new syntax of parameters and arguments seen as a delta from the [sta

```
ClsParamClause ::= ... | UsingClsParamClause
DefParamClauses ::= ... | UsingParamClause
DefParamClause ::= ... | UsingParamClause
UsingClsParamClause ::= ‘(’ ‘using’ (ClsParams | Types) ‘)’
UsingParamClause ::= ‘(’ ‘using’ (DefParams | Types) ‘)’
UsingParamClause ::= ‘(’ ‘using’ (DefTermParams | Types) ‘)’
ParArgumentExprs ::= ... | ‘(’ ‘using’ ExprsInParens ‘)’
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
layout: doc-page
title: "Generalized Method Syntax"
movedTo: https://docs.scala-lang.org/scala3/reference/other-new-features/generalized-method-syntax.html
---

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.

## Syntax Changes

### In Scala 2

The old syntax only allowed zero or one type parameter clause, followed by any number of term clauses, optionnally followed by an implicit clause:

```scala
def foo[T, U](x: T)(y: U)(z: Int, s: String)(a: Array[T])(implicit List[U])
```

### In Scala 3

The new syntax allows any number of type, term and using clause, in any order, optionnaly followed by an implicit clause:
(do note however that [implicit clause are discouraged, in favor of using clauses](https://docs.scala-lang.org/scala3/reference/contextual/relationship-implicits.html))

```scala
def foo[T, U](x: T)(y: U)[V](z: V, s: String)[A](a: Array[A])(implicit List[U])
```

### Unchanged

Class definitions and type declarations are unaffected, there can only be up to one type clause, in leading posion.

## Motivation

The new syntax is a powerful but natural extension of the old one, it allows new design patterns while staying intuitive and legible.

### Dependent Type Clauses

As type clauses can come after term clauses, it is now possible to have type parameters depend on term parameters:

```scala
trait Key { type Value }
trait DB {
def get(k: Key): Option[k.Value] // dependent return type
def getOrElse(k: Key)[V >: k.Value](default: V): V // dependent type parameter
}
```

Note that simply replacing `V` by `k.Value` would not be equivalent. For example, if `k.Value` is `Int`, the above allows:
`getOrElse(k)[Number](0.1)`, which returns a `Number`.

### Partial Inference

It is now possible to only infer some of the type parameters, this reduces boilerplate at the use site:
```scala
trait StaticSizeList[S <: Int & Singleton, T]
def filled[S <: Int & Singleton][T](x: T): StaticSizeList[S,T] = ???
val helloes = filled[4]("Hello!") // S=4, and T is inferred
```

## Details

### Application

Method application is unchanged, in cases where multiple type clauses are expected but not all are passed, the leftmost ones are inferred.

In particular, the following does not type check, even though the argument `Char` is only valid for `C`:
```scala
def triple[A <: Int][B <: String][C <: Char](a: A, b: B, c: C) = ???
triple[Int][Char](0,"",'c') // error: Char does not conform to upperbound String
```

### Extension Methods

Naturally extension methods follow the same syntax, so the following is valid:
```scala
extension [T](l1: List[T])
def zipWith[U](l2: List[U])[V](l3: List[V]): List[(T,U,V)]
```

### Formal syntax

```
DefDcl ::= DefSig ‘:’ Type
DefDef ::= DefSig [‘:’ Type] ‘=’ Expr
DefSig ::= id [DefParamClauses] [DefImplicitClause]
DefParamClauses ::= DefParamClause { DefParamClause }
DefParamClause ::= DefTypeParamClause
| DefTermParamClause
| UsingParamClause
DefTypeParamClause::= [nl] ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’
DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds
DefTermParamClause::= [nl] ‘(’ [DefTermParams] ‘)’
UsingParamClause ::= [nl] ‘(’ ‘using’ (DefTermParams | FunArgTypes) ‘)’
DefImplicitClause ::= [nl] ‘(’ ‘implicit’ DefTermParams ‘)’
DefTermParams ::= DefTermParam {‘,’ DefTermParam}
DefTermParam ::= {Annotation} [‘inline’] Param
Param ::= id ‘:’ ParamType [‘=’ Expr]
```

0 comments on commit 541ec60

Please sign in to comment.