Closed TomasMikula closed 1 year ago
Probably a better workaround would be:
val f: Pair[Int, Pair[String, Boolean]] => String =
Pair(a, Pair(b, c)) => s"($a, ($b, $c))"
But it does have the drawback of requiring a result type.
So I like your proposal, because it also seems to make the language more uniform. It would mean that tuple syntax is no longer special. At the very least, I think this should be accepted:
val f = { case Pair(x: Int, y: Int) => x }
Currently, even this is rejected:
val f = { case (x: Int) => x }
Probably a better workaround would be:
val f: Pair[Int, Pair[String, Boolean]] => String = Pair(a, Pair(b, c)) => s"($a, ($b, $c))"
Well that doesn't compile, perhaps you meant
val f: Pair[Int, Pair[String, Boolean]] => String =
{ case Pair(a, Pair(b, c)) => s"($a, ($b, $c))" }
It would mean that tuple syntax is no longer special.
Note that destructuring in lambdas is not supported even for tuples:
val f = ((a: Int, b: String)) => s"($a, $b)"
1 |val f = ((a: Int, b: String)) => s"($a, $b)"
| ^^^^^^^^^^^^^^^^^^^
| not a legal formal parameter
At the very least, I think this should be accepted:
val f = { case Pair(x: Int, y: Int) => x }
I think the convention is that case
means a runtime check. Then this code, if accepted, would define a PartialFunction[Any, Int]
, not Pair[Int, Int] => Int
.
Yes, I agree with your points, except the last one.
The convention that "case
means a runtime check" does not really exist in practice. You can use case
to define both normal and partial function literals, depending on the expected type. And since currently there is no way of writing case
-defined lambdas without an expected type, there is no convention that case
relates to runtime checks and PartialFunction
in particular. IIRC the Scala spec does call case
-defined lambdas "partial function literals" or something like that, but in practice there is no such distinction. On a related note, the typing of x =>
may differ from that of case x =>
because the latter triggers GADT reasoning (at least in Scala 2), so they are not interchangeable either.
I propose to support destructuring lambdas, i.e. function definitions in which the parameter is deconstructed via a pattern.
Example:
An important part of this feature is that the pattern would drive type inference: The type ascriptions
a: Int
,b: String
,c: Boolean
in the pattern above are not type tests; they are constraints for type inference/type checking. The compiler would infer the type off
to bePair[Int, Pair[String, Boolean]] => String
.Workaround
The currently available workaround is to do a destructuring assignment as the first thing in the lambda body:
We can see the repetitiveness as well as the need to introduce an intermediate name
t
.