Skip to content

Commit d91fa07

Browse files
committed
Add spec for auto-tupling of n-ary functions
1 parent 7087a6c commit d91fa07

File tree

3 files changed

+86
-1
lines changed

3 files changed

+86
-1
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
layout: doc-page
3+
title: "Automatic Tupling of Function Parameters - More Details"
4+
---
5+
6+
### Motivation
7+
8+
Say you have a list of pairs
9+
10+
```scala
11+
val xs: List[(Int, Int)]
12+
```
13+
14+
and you want to map `xs` to a list of `Int`s so that each pair of numbers is mapped to their sum.
15+
Previously, the best way to do this was with a pattern-matching decomposition:
16+
```scala
17+
xs.map {
18+
case (x, y) => x + y
19+
}
20+
```
21+
While correct, this is also inconvenient. Instead, automatic tupling of function parameters proposed to be able to write it the following way:
22+
23+
```scala
24+
xs.map {
25+
(x, y) => x + y
26+
}
27+
```
28+
or, equivalently:
29+
```scala
30+
xs.map(_ + _)
31+
```
32+
33+
Generally, a function value with `n > 1` parameters can be converted to a pattern-matching closure using case if the expected type is a unary function type of the form `((T_1, ..., T_n)) => U`.
34+
35+
### Type Checking
36+
37+
Let a function `F` of the form `F = (p1, ..., pn) => E` for `n != 1`, parameters `p1, ..., pn`, and an expression `E`.
38+
39+
40+
If the expected type of `F` is a fully defined function type or SAM-type that has a
41+
single parameter of a subtype of `ProductN[T1, ..., Tn]`, where each type `Ti` fits the corresponding
42+
parameter `pi`.
43+
44+
A type `T` fits a parameter `p` if one of the following two cases is `true`:
45+
46+
* `p` comes without a type, i.e. it is a simple identifier or `_`.
47+
* `p` is of the form `x: U` or `_: U` and `T` conforms to `U`.
48+
49+
Auto-tupling composes with eta-expansion. That is an n-ary function generated by eta-expansion
50+
can in turn be adapted to the expected type with auto-tupling.
51+
52+
#### Term addaptation
53+
54+
If the a function
55+
```scala
56+
(p1: T1, ..., pn: Tn) => E
57+
```
58+
59+
is typed as `ProductN[T1, ..., Tn] => Te`, then it will be transformed to
60+
61+
```scala
62+
(x: TupleN[T1, ..., Tn]) => {
63+
def p1: T1 = x._1
64+
...
65+
def pn: Tn = x._n
66+
E
67+
}
68+
```
69+
70+
### Migration
71+
72+
Code like this could not be written before, hence the new notation would not be ambigouous after addoptation.
73+
74+
Thought it is possible that someone has written an implicit conversion for `(T1, ..., Tn) => R` into `TupleN[T1, ..., Tn]`
75+
for some `n`. This change could be detected and fixed by `Scalafix`. Furthermore, such conversion would probably
76+
be doing the same translation (semantically) but in a less efficient way.
77+
78+
### Reference
79+
80+
For more info see:
81+
* [Issue #897](https://github.com/lampepfl/dotty/issues/897).

docs/docs/reference/auto-parameter-tupling.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ function type of the form `((T_1, ..., T_n)) => U`.
3030

3131
### Reference
3232

33-
For more info, see [Issue #897](https://github.com/lampepfl/dotty/issues/897).
33+
For more info see:
34+
* [More details](./auto-parameter-tupling-spec.html)
35+
* [Issue #897](https://github.com/lampepfl/dotty/issues/897).

docs/sidebar.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ sidebar:
5353
url: docs/reference/implicit-by-name-parameters.html
5454
- title: Auto Parameter Tupling
5555
url: docs/reference/auto-parameter-tupling.html
56+
- title: Auto Parameter Tupling - More Details
57+
url: docs/reference/auto-parameter-tupling-spec.html
5658
- title: Named Type Arguments
5759
url: docs/reference/named-typeargs.html
5860
- title: Erased Terms

0 commit comments

Comments
 (0)