Skip to content

More details on named type arguments #5326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions docs/docs/reference/named-typeargs-spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
layout: doc-page
title: "Named Type Arguments - More Details"
---

## Syntax

The addition to the grammar is:

```
SimpleExpr1 ::= ...
| SimpleExpr (TypeArgs | NamedTypeArgs)
NamedTypeArgs ::= ‘[’ NamedTypeArg {‘,’ NamedTypeArg} ‘]’
NamedTypeArg ::= id ‘=’ Type
```

Note in particular that named arguments cannot be passed to type constructors:

``` scala
class C[T]

val x: C[T = Int] = // error
new C[T = Int] // error

class E extends C[T = Int] // error
```

## Compatibility considerations

Named type arguments do not have an impact on binary compatibility, but they
have an impact on source compatibility: if the name of a method type parameter
is changed, any existing named reference to this parameter will break. This
means that the names of method type parameters are now part of the public API
of a library.

(Unimplemented proposal: to mitigate this,
[`scala.deprecatedName`](https://www.scala-lang.org/api/current/scala/deprecatedName.html)
could be extended to also be applicable on method type parameters.)
23 changes: 13 additions & 10 deletions docs/docs/reference/named-typeargs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@ title: "Named Type Arguments"

Type arguments of methods can now be named, as well as by position. Example:

``` scala
def construct[Elem, Coll[_]](xs: Elem*): Coll[Elem] = ???

def construct[Elem, Coll[_]](xs: Elem*): Coll[Elem] = ???

val xs2 = construct[Coll = List, Elem = Int](1, 2, 3)
val xs3 = construct[Coll = List](1, 2, 3)
val xs1 = construct[Coll = List, Elem = Int](1, 2, 3)
val xs2 = construct[Coll = List](1, 2, 3)
```

Similar to a named value argument `(x = e)`, a named type argument
`[X = T]` instantiates the type parameter `X` to the type `T`. Type
arguments must be all named or un-named, mixtures of named and
positional type arguments are not supported.

The main benefit of named type arguments is that they allow some
arguments to be omitted. Indeed, if type arguments are named, some
arguments may be left out. An example is the definition of `xs3`
above. A missing type argument is inferred as usual by local type
inference. The same is not true for positional arguments, which must always
be provided for all type parameters.
## Motivation

The main benefit of named type arguments is that unlike positional arguments,
you are allowed to omit passing arguments for some parameters, like in the
definition of `xs2` above. A missing type argument is inferred as usual by
local type inference. This is particularly useful in situations where some type
arguments can be easily inferred from others.

[More details](./named-typeargs-spec.html)
4 changes: 4 additions & 0 deletions tests/neg/namedTypeParams.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ object Test {
class E extends C[T = Int] // error: ']' expected, but `=` found // error
class F extends C[T = Int]() // error: ']' expected, but `=` found // error

def f[X, Y](x: X, y: Y): Int = ???

f[X = Int, String](1, "") // error
f[X = Int][X = Int][Y = String](1, "") // error
}
6 changes: 6 additions & 0 deletions tests/pos/namedTypeParams.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,10 @@ object Test {
f[X = Int, Y = String](1, "")
f[X = Int](1, "")
f[Y = String](1, "")

f[X = Int][Y = String](1, "")
f[X = Int][String](1, "")

f[Y = String][X = Int](1, "")
f[Y = String][Int](1, "")
}