Skip to content

Commit

Permalink
Merge pull request #14315 from som-snytt/tweak/untupling
Browse files Browse the repository at this point in the history
Mention general conversions for untupling
  • Loading branch information
OlivierBlanvillain authored Jan 27, 2022
2 parents 6353ed9 + 58c795a commit afbb5a5
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ is feasible for parameter untupling with the expected type `TupleN[T1, ..., Tn]
with the same expected type.
## Migration

Code like this could not be written before, hence the new notation would not be ambiguous after adoption.
Code like this could not be written before, hence the new notation is not ambiguous after adoption.

Though it is possible that someone has written an implicit conversion form `(T1, ..., Tn) => R` to `TupleN[T1, ..., Tn] => R`
for some `n`. This change could be detected and fixed by [`Scalafix`](https://scalacenter.github.io/scalafix/). Furthermore, such conversion would probably
be doing the same translation (semantically) but in a less efficient way.
It is possible that someone has written an implicit conversion from `(T1, ..., Tn) => R` to `TupleN[T1, ..., Tn] => R` for some `n`.
Such a conversion is now only useful for general conversions of function values, when parameter untupling is not applicable.
Some care is required to implement the conversion efficiently.
Obsolete conversions could be detected and fixed by [`Scalafix`](https://scalacenter.github.io/scalafix/).

## Reference

Expand Down
31 changes: 31 additions & 0 deletions docs/docs/reference/other-new-features/parameter-untupling.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,42 @@ or, equivalently:
```scala
xs.map(_ + _)
```
and
```scala
def combine(i: Int, j: Int) = i + j
xs.map(combine)
```

Generally, a function value with `n > 1` parameters is 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`.

More specifically, the adaptation is applied to the mismatching formal
parameter list. In particular, the adaptation is not a conversion
between function types. That is why the following is not accepted:

```scala
val combiner: (Int, Int) => Int = _ + _
xs.map(combiner) // Type Mismatch
```

The function value must be explicitly tupled, rather than the parameters untupled:
```scala
xs.map(combiner.tupled)
```

A conversion may be provided in user code:

```scala
import scala.language.implicitConversions
transparent inline implicit def `fallback untupling`(f: (Int, Int) => Int): ((Int, Int)) => Int =
p => f(p._1, p._2) // use specialized apply instead of unspecialized `tupled`
xs.map(combiner)
```

Parameter untupling is attempted before conversions are applied, so that a conversion in scope
cannot subvert untupling.

## Reference

For more information see:
Expand Down

0 comments on commit afbb5a5

Please sign in to comment.