Skip to content

Mention general conversions for untupling #14315

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
Jan 27, 2022
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
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