If we retire try
, then the compiler can avoid the import conflict between util.Try
and Trees.Try
.
That alone would be a huge productivity boost for the small compiler team.
Although I once admired the uniformity of syntax for match
and catch
, it has broken down with the introduction of one-line catch without one-line match.
Instead of
try throw null catch case _: NullPointerException => "null"
we could
throw null match catch _: NullPointerException => "null"
and of course agnostically for irrefutable patterns
"[email protected]" match case Email(user, _) => user
The other grievous omission is the lack of natch
syntax, which serves nicely to replace finally
, as it is the “natural” exit from a computation, without respect to normal or abnormal completion.
We’re not supposed to use exceptions for flow control, but having sampled the forbidden fruit of non-local return
and break
, we can hardly do without it. I agree in part with the proposal to make aborts syntactically less baroque, though not with the goal of obscuring their exceptional nature (because of other effects such as whether a thread is interrupted).
Exceptions are not like normal result values that can be ignored for now; normal values can be discarded, but exception handling is part of every design analysis, even if no exceptions are handled; that is, exceptions are never ignored.
I would be onboard with throw v
syntax that wraps my value and unwraps it in catch v: V
.
e match
case K => "k"
catch Erroneous(fail) => s"failed with $fail"
case if p => "predicate held"
natch => println("how'm I doing?")
match
case "k" => throw Error("expected to fail as usual")
catch Fail(pfail) => s"failed evaluating predicate with $pfail"
catch r: RuntimeException => s"little hiccup $r"
case x => s"some result $x"
I don’t see why the syntax should force me to write my catch
later or my natch
last of all.
e match
catch Error(msg) => handle(msg) // handle early exit
case ...
I tossed in case if
but not case =>
to replace case _ =>
because I use underscore to mean “I’m not interested in the selector” and not merely “I don’t need to rebind it”. It is analogous to underscore in an import clause. If I use the value:
v match
case v => s"It was $v" // redundancy indicates I intend to use the value,
// and the name is nearby, if the selector is many lines away
For completeness, case x
where the pattern is just a var could be called a patch
for “pattern char”, though I don’t propose syntax for it.