<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
To the question “does Java need this”, well, of course we don’t *need* it; we do have try-catch statements. But as Dan points out, the main challenge of using methods that both return a value and throw exceptions is that we cannot handle all the results uniformly.
And as the JEP points out, backing off to try-catch is doubly painful: not only do we have to use two constructs, but we are back to statement-land, which is far more error prone and less composable than expressions.
<div class=""><br class="">
</div>
<div class="">As to “why don’t we just make try-catch an expression”, well, that’s where we started with this feature exploration. It turns out to just be too weak to be useful. The main constraint is that the try and catch parts have to yield the same type,
but the constraint to produce a “default” value of that type from the catch arms is just too constraining. If you try some nontrivial examples this becomes clear pretty quickly. </div>
<div class=""><br class="">
</div>
<div class="">But there is one criticism of this feature that is I think at the root of what you are getting at, which is that having effect cases in switch produces only a shallow-ish unification (or, alternately, that it is not the primitive.) Having effect
cases lets us deal uniformly with all the consequences of evaluating the selector uniformly in one place, but like try-catch, you have to deal with them _right there_. Whereas with a Try monad, you could capture the Try and then process it by passing it to
another method, putting it on a queue and letting some other thread process it, etc. </div>
<div class=""><br class="">
</div>
<div class="">If we were to excavate to the bottom, then we would likely want `try e` to evaluate to a Try monad, at which point the current proposal is a sugary representation of:</div>
<div class=""><br class="">
</div>
<div class=""> switch (try e) { </div>
<div class=""> case Success(P1) -> …</div>
<div class=""> case Success(P2) -> …</div>
<div class=""> case Failure(E1) -> …</div>
<div class=""> }</div>
<div class=""><br class="">
</div>
<div class="">We explored this point as well in the exploration, and backed off. But we can do this in either order; if we have a `try e` primitive that evaluates to a Try, then we can retroactively redefine a switch with `case throws` clauses to be sugar
for the above. </div>
<div class=""><br class="">
</div>
<div class="">I will think further about the pattern matching connection you propose.</div>
<div class="">
<div><br class="">
<blockquote type="cite" class="">
<div class="">On Apr 20, 2024, at 10:00 AM, Tagir Valeev <<a href="mailto:amaembo@gmail.com" class="">amaembo@gmail.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div dir="ltr" class="">Dear experts,
<div class=""><br class="">
</div>
<div class="">looking into this proposal, I'm really not convinced that Java needs it. We already have try-catch statements, and it sounds strange to provide another way to express the same semantics. I don't see what the new construct adds, aside from a bit
of syntactic sugar. On the other hand, it creates a new source of subtle bugs, especially when exceptions are unchecked. E.g., consider:</div>
<div class=""><br class="">
</div>
<div class="">switch(a.b().c().d()) {</div>
<div class="">case ...</div>
<div class="">case throws RuntimeException ex -> handle(ex);</div>
<div class="">}</div>
<div class=""><br class="">
</div>
<div class="">Now, one may want to refactor the code, extracting a.b(), a.b().c(), or the whole a.b().c().d() to a separate variable for clarity, or to avoid a long line. </div>
<div class="">This action is usually safe, and it was totally safe in switches so far (even with patterns and case null). Now, it's not safe, as exceptions thrown from the extracted part are not handled by the 'case throws' branch. </div>
<div class="">I don't see a good way to perform this refactoring in a semantically equivalent way. The only possibility I see is to duplicate the exception handler in the external catch:</div>
<div class=""><br class="">
</div>
<div class="">try {</div>
<div class=""> var ab = a.b();</div>
<div class=""> switch(ab.c().d()) {</div>
<div class=""> case ...</div>
<div class=""> case throws RuntimeException ex -> handle(ex);</div>
<div class=""> }</div>
<div class="">}<br class="">
</div>
<div class="">catch(RuntimeException ex) {</div>
<div class=""> handle(ex); // duplicated code</div>
<div class="">}</div>
<div class=""><br class="">
</div>
<div class="">As switch selector does not allow using several expressions or to declare new variables, extract/inline refactorings can easily become very painful, or cause subtle bugs if not performed correctly. </div>
<div class="">Note that it's not a problem inside usual try-catch statement (*), as you can easily add or remove more statements inside the try-body.</div>
<div class=""><br class="">
</div>
<div class="">(*) Except resource declaration, but it's rarely a problem, and in some cases it's still possible to extract parts as separate resources, because you can declare several of them<br class="">
</div>
<div class=""><br class="">
</div>
<div class="">I think, instead of repurposing switch to be another form of try-catch we could add more love to try-catch allowing it to be an expression with yields in branches. The proposed JEP allows something like this:</div>
<div class=""><br class="">
</div>
<div class="">Integer toIntOrNull(String s) {</div>
<div class=""> return switch(Integer.parseInt(s)) {</div>
<div class=""> case int i -> i;</div>
<div class=""> case throws NumberFormatException _ -> null;</div>
<div class=""> }</div>
<div class="">}</div>
<div class=""><br class="">
</div>
<div class="">But we are still limited by a single expression in the selector. An alternative would be</div>
<div class="">
<div class="">Integer toIntOrNull(String s) {</div>
<div class=""> return try { yield Integer.parseInt(s); }</div>
<div class=""> catch(NumberFormatException _) { yield null; };</div>
<div class="">}<br class="">
</div>
<div class="">Here, all kinds of refactorings are possible. And we actually don't need to express pattern matching, because we essentially don't need any pattern matching.</div>
</div>
<div class=""><br class="">
</div>
<div class="">Also, note that some of the situations which are usually solved with exception handling in modern Java (e.g. Pattern.compile -> PatternSyntaxException, or UUID.fromString -> IllegalArgumentException, or Integer.parseInt above) will be covered
in future by member patterns. So probably if we concentrate more on member patterns, people will need much less exception handling in business logic, and such an enhancement will be not so useful anyway? Speaking about the sample from the JEP, can we imagine
something like this in the future (sic!) Java?</div>
<div class=""><br class="">
</div>
<div class="">switch(future) {</div>
<div class=""> case Future.cancelled() -> ...</div>
<div class=""> case Future.interrupted() -> ...</div>
<div class=""> case Future.failed(Exception ex) -> ... // no need to unwrap ExecutionException manually</div>
<div class=""> case Future.successful(Box b) -> ...</div>
<div class="">}</div>
<div class=""><br class="">
</div>
<div class="">One more note about the JEP text. It's unclear for me whether 'case throw' branches could catch a residual result. More precisely, if MatchException happens, or NullPointerException happens (selector evaluated to null, but there's no 'case null'),
can these exceptions be caught by the 'case throws' branches in the same switch?</div>
<div class=""><br class="">
</div>
<div class="">With best regards,</div>
<div class="">Tagir Valeev.</div>
<div class=""><br class="">
</div>
</div>
<br class="">
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Fri, Apr 19, 2024 at 3:05 PM Angelos Bimpoudis <<a href="mailto:angelos.bimpoudis@oracle.com" class="">angelos.bimpoudis@oracle.com</a>> wrote:<br class="">
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="msg-8195856652776668133">
<div dir="ltr" class="">
<div style="font-size: 11pt;" class="">Dear spec experts,</div>
<div style="font-size: 11pt;" class=""><br class="">
</div>
<div style="font-size: 11pt;" class="">A while ago we discussed on this list about enhancing the
<code class="">switch</code> construct to</div>
<div style="font-size: 11pt;" class="">support <code class="">case</code> labels that match exceptions thrown during evaluation of the</div>
<div style="font-size: 11pt;" class="">selector expression. A draft JEP for this feature is now available at:</div>
<div style="font-size: 11pt;" class=""><br class="">
</div>
<div style="font-size: 11pt;" class=""><a href="https://bugs.openjdk.org/browse/JDK-8323658" target="_blank" class="">https://bugs.openjdk.org/browse/JDK-8323658</a></div>
<div style="font-size: 11pt;" class=""><br class="">
</div>
<div style="font-size: 11pt;" class="">Please take a look at this new JEP and give us your feedback.</div>
<div style="font-size: 11pt;" class=""><br class="">
</div>
<div style="font-size: 11pt;" class="">Thanks,</div>
<div style="font-size: 11pt;" class="">Aggelos</div>
</div>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
<br class="">
</div>
</body>
</html>