Skip to content

Commit

Permalink
Apply limit22.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Sporarum authored and sjrd committed Apr 28, 2023
1 parent 4ef7f60 commit d5e2a69
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 27 deletions.
38 changes: 22 additions & 16 deletions docs/_spec/03-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,22 +217,27 @@ G[S, Int] // illegal: S constrains its parameter to
SimpleType ::= ‘(’ Types ‘)’
```

A _tuple type_ ´(T_1 , ... , T_n)´ is an alias for the class `scala.Tuple´n´[´T_1´, ... , ´T_n´]`, where ´n \geq 2´.
A _tuple type_ ´(T_1, ..., T_n)´ where ´n \geq 2´ is an alias for the type `´T_1´ *: ... *: ´T_n´ *: scala.EmptyTuple`.

Note:
`(´T´)` is just the type ´T´, and not `´T´ *: scala.EmptyTuple`.
`()` is not a valid type, and not `scala.EmptyTuple`.

If ´n \leq 22´, the type `´T_1´ *: ... *: ´T_n´ *: scala.EmptyTuple` is both a subtype and a supertype of tuple class `scala.Tuple´_n´[´T_1´, ..., ´T_n´]`.

Tuple classes are case classes whose fields can be accessed using selectors `_1`, ..., `_n`.
Their functionality is abstracted in a corresponding `Product` trait.
Their functionality is abstracted in the corresponding `scala.Product_´n´` trait.
The _n_-ary tuple class and product trait are defined at least as follows in the standard Scala library (they might also add other methods and implement other traits).

```scala
case class Tuple´_n´[+´T_1´, ..., +´T_n´](_1: ´T_1´, ..., _n: ´T_n´)
extends Product´_n´[´T_1´, ..., ´T_n´]

trait Product´_n´[+´T_1´, ..., +´T_n´] {
trait Product´_n´[+´T_1´, ..., +´T_n´] extends Product:
override def productArity = ´n´
def _1: ´T_1´
...
def _n: ´T_n´
}
```

### Annotated Types
Expand Down Expand Up @@ -329,25 +334,26 @@ FunctionArgs ::= InfixType
| ‘(’ [ ParamType {‘,’ ParamType } ] ‘)’
```

The type ´(T_1, ..., T_n) \Rightarrow U´ represents the set of function values that take arguments of types ´T_1, ..., Tn´ and yield results of type ´U´.
In the case of exactly one argument type ´T \Rightarrow U´ is a shorthand for ´(T) \Rightarrow U´.
An argument type of the form ´\Rightarrow T´ represents a [call-by-name parameter](04-basic-declarations-and-definitions.html#by-name-parameters) of type ´T´.
The type ´(T_1, ..., T_n) \Rightarrow R´ represents the set of function values that take arguments of types ´T_1, ..., Tn´ and yield results of type ´R´.
The case of exactly one argument type ´T \Rightarrow R´ is a shorthand for ´(T) \Rightarrow R´.
An argument type of the form ´\Rightarrow T´ represents a [call-by-name parameter](04-basic-declarations-and-definitions.md#by-name-parameters) of type ´T´.

Function types associate to the right, e.g. ´S \Rightarrow T \Rightarrow U´ is the same as ´S \Rightarrow (T \Rightarrow U)´.
Function types associate to the right, e.g. ´S \Rightarrow T \Rightarrow R´ is the same as ´S \Rightarrow (T \Rightarrow R)´.

Function types are [covariant](04-basic-declarations-and-definitions.md#variance-annotations) in their result type and [contravariant](04-basic-declarations-and-definitions.md#variance-annotations) in their argument types.

Function types are shorthands for class types that define an `apply` method.
Specifically, the ´n´-ary function type ´(T_1 , \ldots , T_n) \Rightarrow U´ is a shorthand for the class type `Function´_n´[´T_1´ , … , ´T_n´, ´U´]`.
Such class types are defined in the Scala library for ´n´ between 0 and 22 as follows.
Specifically, the ´n´-ary function type ´(T_1, ..., T_n) \Rightarrow R´ is a shorthand for the class type `Function´_n´[´T_1´, ..., ´T_n´, ´R´]`.
In particular ´() \Rightarrow R´ is a shorthand for class type `Function´_0´[´R´]`.

Such class types behave as if they were instances of the following trait:

```scala
package scala
trait Function´_n´[-´T_1´, ..., -´T_n´, +´U´] {
def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´U´
override def toString = "<function>"
}
trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´
```

Hence, function types are [covariant](04-basic-declarations-and-definitions.html#variance-annotations) in their result type and contravariant in their argument types.
Their exact supertype and implementation can be consulted in the [function classes section](./12-the-scala-standard-library.md#the-function-classes) of the standard library page in this document.

#### Wildcard Types

Expand Down
13 changes: 11 additions & 2 deletions docs/_spec/06-expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,9 +381,15 @@ Type applications can be omitted if [local type inference](#local-type-inference
```ebnf
SimpleExpr ::= ‘(’ [Exprs] ‘)’
```
A _tuple expression_ `(´e_1´, ..., ´e_n´)` where ´n \geq 2´ is equivalent to the expression `´e_1´ *: ... *: ´e_n´ *: scala.EmptyTuple`.

A _tuple expression_ `(´e_1´, ..., ´e_n´)` is an alias for the class instance creation `scala.Tuple´n´(´e_1´, ..., ´e_n´)`, where ´n \geq 2´.
The empty tuple `()` is the unique value of type `scala.Unit`.
Note:
As calls to `*:` are slow, a more efficient translation is free to be implemented.
For example, `(´e_1´, ´e_2´)` could be translated to `scala.Tuple2(´e_1´, ´e_2´)`, which is indeed equivalent to `´e_1´ *: ´e_2´ *: scala.EmptyTuple`.

Note:
The expression `(´e_1´)` is not equivalent to `´e_1´ *: scala.EmptyTuple`, but instead a regular parenthesized expression.
The expression `()` is not an alias for `scala.EmptyTuple`, but instead the unique value of type `scala.Unit`.

## Instance Creation Expressions

Expand Down Expand Up @@ -909,6 +915,9 @@ Binding ::= (id | ‘_’) [‘:’ Type]
The anonymous function of arity ´n´, `(´x_1´: ´T_1, ..., x_n´: ´T_n´) => e` maps parameters ´x_i´ of types ´T_i´ to a result given by expression ´e´.
The scope of each formal parameter ´x_i´ is ´e´.
Formal parameters must have pairwise distinct names.
Type bindings can be omitted, in which case the compiler will attempt to infer valid bindings.

Note: `() => ´e´` defines a nullary function (´n´ = 0), and not for example `(_: Unit) => ´e´`.

In the case of a single untyped formal parameter, `(´x\,´) => ´e´` can be abbreviated to `´x´ => ´e´`.
If an anonymous function `(´x´: ´T\,´) => ´e´` with a single typed parameter appears as the result expression of a block, it can be abbreviated to `´x´: ´T´ => e`.
Expand Down
10 changes: 9 additions & 1 deletion docs/_spec/08-pattern-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,15 @@ This is further discussed [here](#pattern-sequences).
SimplePattern ::= ‘(’ [Patterns] ‘)’
```

A _tuple pattern_ `(´p_1´, ..., ´p_n´)` is an alias for the constructor pattern `scala.Tuple´n´(´p_1´, ..., ´p_n´)`, where ´n \geq 2´. The empty tuple `()` is the unique value of type `scala.Unit`.
A _tuple pattern_ `(´p_1´, ..., ´p_n´)` where ´n \geq 2´ is equivalent to `´p_1´ *: ... *: ´p_n´ *: scala.EmptyTuple`.

Note:
`()` is equivalent to `_: scala.Unit`, and not `scala.EmptyTuple`.
`(´pat´)` is a pattern matching ´pat´, and not `´pat´ *: scala.EmptyTuple`.

Note:
As such patterns with `*:` are slow, a more efficient translation is free to be implemented.
For example, `(´p_1´, ´p_2´)` could be translated to `scala.Tuple2(´p_1´, ´p_2´)`, which is indeed equivalent to `´p_1´ *: ´p_2´ *: scala.EmptyTuple`.

### Extractor Patterns

Expand Down
36 changes: 28 additions & 8 deletions docs/_spec/12-the-scala-standard-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ def + (that: Any): String

which concatenates its left operand with the textual representation of its right operand.

<!-- TODO: re-add ? with explanations of: EmptyTuple, *:, NonEmptyTuple, TupleXXL
### The `Tuple` classes
Scala defines tuple classes `Tuple´n´` for ´n = 2, ..., 22´.
Expand All @@ -299,20 +300,36 @@ case class Tuple´n´[+T_1, ..., +T_n](_1: T_1, ..., _´n´: T_´n´) {
def toString = "(" ++ _1 ++ "," ++ ... ++ "," ++ _´n´ ++ ")"
}
```

-->
### The `Function` Classes

Scala defines function classes `Function´n´` for ´n = 1 , \ldots , 22´.
These are defined as follows.
For each class type `Function´n´` where ´n = 0, ..., 22´, Scala defines the following function class:

```scala
package scala
trait Function´n´[-T_1, ..., -T_´n´, +R] {
def apply(x_1: T_1, ..., x_´n´: T_´n´): R
def toString = "<function>"
}
trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´
override def toString = "<function´_n´>"
def curried: ´T_1´ => ... => ´T_n´ => R = ...
def tupled: ((´T_1´, ..., ´T_n´)) => R = ...
```

For function types `Function´n´` where ´n > 22´, Scala defines a unique function class:

```scala
package scala
trait FunctionXXL:
def apply(xs: IArray[Object]): Object
override def toString = "<functionXXL>"
```

There is no loss of type safety, as the internal representation is still `Function´n´` for all ´n´.
However this means methods `curried` and `tupled` are not available on functions with more than 22 parameters.

The implicitly imported [`Predef`](#the-predef-object) object defines the name
`Function` as an alias of `Function1`.

<!-- TODO: Remove below ? -->
The `PartialFunction` subclass of `Function1` represents functions that (indirectly) specify their domain.
Use the `isDefined` method to query whether the partial function is defined for a given input (i.e., whether the input is part of the function's domain).

Expand All @@ -322,7 +339,10 @@ class PartialFunction[-A, +B] extends Function1[A, B] {
}
```

The implicitly imported [`Predef`](#the-predef-object) object defines the name `Function` as an alias of `Function1`.
### Trait `Product`
<!-- TODO: Move somewhere else ? -->
<!-- TODO: Could not find more info on which non-Product methods case class automatically define -->
All case classes automatically extend the `Product` trait (and generate synthetic methods to conform to it) (but not `Product´n´`), and define a `_´n´` method for each of their arguments.

### Class `Array`

Expand Down

0 comments on commit d5e2a69

Please sign in to comment.