The downsides are it requires two imports, one of which enables a feature considered dangerous, and the braces around the method are required (otherwise the compiler thinks that (num, name) are arguments to pipe).
Incidentally, I’d love the automatic untupling to be backported, but I’m not sure how much work that would be for the compiler team.
On a complete tangent, I have no idea why chaining isn’t easier to bring in (I’d love it in Predef, to be honest), but hopefully the implementation will be changed to something that doesn’t involve implicit conversions and remove that wart.
My example is not comprehensive enough. It could be a tuple to be untupled, or it could be any case class to be destrcutured.
We could also do the same thing to try catch, like:
try {
throw new Exception()
} catch case _: Exception => {
println("Exception caught")
}
instead of
try {
throw new Exception()
} catch {
case _: Exception => {
println("Exception caught")
}
}
I agree pipe should be easier to use, and I think with this change, it is very close to what I try to achieve. I definitely prefer a simple match case to pipe { case }. It avoids additional imports and additional lambda construct
The reason it does not work for match is that the two play different roles in the syntax.
matches can be chained and mixed with normal calls. That means
expr match {
...
}
is seen as an expression with fairly high precedence (same as alphanumeric operators). But that convention can be upheld only if the right hand side of match is atomic.
Anyway, I think try is the more important usecase since a single case match can also expressed as a pattern binding:
val Transaction(num, name) = getTransaction(100, "Amount")
println(s"$name has amount of $num")
Great to see it already works with try-catch! Is there any plan to backport that into Scala 2?
Yes val can also destructure the object, but it requires two statements as you mentioned. When we have a series of objects to process, it gets tedious. I definitely agree that the convention can be upheld if it is a single case on the right hand side.
True. But if you have a few matches in a chain, some of them being in { case …} form, some of them being pre-defined functions, you will have to flip the sides around every time; having the thing to match with once on the left side, other times on the right side (and additionally have need to invent new variable names for the in-between steps) which seems a little confusing.
The alternative would be to write match { case x => f(x) }. This is a total match, so it makes sense to maybe allow omitting the case, leaving match { x => f(x) }, which again feels like it could be shortened as usual to match f.
I guess part of my reasoning comes from the fact that I already can define (or import) my own pipe operator @alpha("match") def [A, B](x: A) |> (y: Function[A, B]): B = y(x) which gives me exactly that (or so it seems), so it is not totally clear to me why match has to be more restrictive, unless there are syntactic or type-checking reasons in the way.
@odersky How can I move forward with this proposal? I can also help with the implementation. Shall we implement this in dotty with all the other syntax changes?
I already explained why it’s problematic to move forward with the proposal. So it’s not a matter of implementation. The implementation existed but was not merged for the problems I mentioned. I do not see what could make the problems go away.