A try expression try { b } catch e1 finally e2
is a shorthand for try { try { b } catch e1 } finally e2
The shorthand is baroque and may be removed. Then it would be possible drop the try keword, before both catch and finally.
e1 finally e2
e1 catch e2
Now the catch construct became much like the match:
e1 match e2
e1 catch e2
It could even be possible to combine the match/catch expression:
e1 match e2 catch e3
e3 would then handle exceptions occurring in e1, but not those in e2.
So when e1 has ended the execution selects between a success branch and a failure branch, depending on whether an exception had occurred.
There is currently not an easy way in Scala to specify such branching on general expressions; yet it would be similar to if-then-else, and to the onComplete method of futures.
The try keyword is very important, as it clearly marks the beginning of a protected section where exceptions will flow differently. Removing it will make it much harder to reason about actual programs. And thatâs irrespective of any potential simplification.
Also, the thing after the try is very often a block. Nobody wants to write
{
val x = foo()
bar(y)
} catch ...
Without the initial try it is totally unreadable. It gets even worse when you realize that you often need a blank line before a bare block like that.
The same does not apply to match because the thing on the left is typically a short expression. And if itâs not short, you can extract it in a val first. You cannot do that with the try block because the block would not be protected by the try anymore.
This is really surprising behavior. This would be a break with how dropped parens are handled, which seems ill-advised in the single most dangerous language construct in Scala.
It seems really counter to how Scala usually binds expressions for e1 match e2 catch e3 to be equivalent to this:
Amazing proposal! If anything can throw anything, whatâs the point of try?
âThere is no try,â as I think someone has already joked.
To sjrdâs point, you can always wrap the throwing expr in locally. To give it a name.
I still need to study the other response about âthe single most dangerous language construct in Scalaâ, but I do sense the need for a t-shirt with that slogan. Maybe just with Martin Oderskyâs profile photo?
Just to be pedantic, you could extract the try block to a def. I think it would behave basically the same (except for an extra frame in the stack trace).
I agree that having try before makes it a lot easier for people reading the code.
Extracting the block to a def seems like it would result in having a chunk of code which is known to throw exceptions, divorced from any indication that the programmer who originally wrote it understood this.
Sebastienâs case (and I apologize that Iâm too American to do the accent without cutting and pasting) is that we canât tell what is an expression.
We should be doing more of e.ensuring(f) and e.tap(f) and therefore also e match pf and e catch pf.
Maybe we also make match and therefore catch just members of Any. e.catch { pf }.
The fact that we are brainwashed by try syntax is no reason to retain it.
The open question is whether to keep Try(e) or prefer e.try.
Letâs recall that part of the brainwashing is that it was so cool that f { body } looks like built-in syntax.
That is still cool, but we donât care about that. For âuniversalâ stuff such as âIâd like to catch exceptions hereâ, the suffix notation is totally fine. The expression ought to be small. e.try instead of
I havenât studied whether Odersky syntax, which we may now call quiet control syntax with optional braces, is amenable to the suffix and infix notations. I think itâs appropriate to call it Odersky syntax because Dr Odersky exudes a vibe of quiet control.
Yet a construct that combines match and catch is missing from the language. A clearer construct with the existing keyword with would be
e1 match e2 with catch e3
So this match-with-catch would work like a futureâs onComplete method.
Thinking along this line: using the keyword yield here would yield more idiomatic alternatives for the methods onComplete, onSuccess and onFailure of futures:
f yield match e
f yield catch e
f yield match e1 with catch e2
The compiler would translate these to method calls: yield_match, yield_catch and yield_match_with_catch. The recipient should be of a type Yield_match_catch_handler or so.
For a future f as a recipient of yield match etc, an implicit conversion should be in scope that turns f into a Yield_match_catch_handler with methods yield_match, yield_catch and yield_match_with_catch calling the futureâs onSuccess and onFailure methods.
Iâd recommend avoiding the term âbrainwashedâ as it is a heavily loaded term in English.
Please keep in mind these are not equivalent. Among other differences, Try will only handle non-fatal exceptions.
I donât really think that it is. Even without quiet control syntax, this is valid Scala 2 code:
try readList() match {
case Nil => 1
case x :: xs => 2
} catch {
case _: java.io.IOException => 3
case _: java.lang.Error => 4
}
This would be problematic, because (as implied above by the note about try/Try non-equivalence) the current behavior of try and Futureâs error handling are not equivalent.
If itâs really true that someone reading this can have their PTSD triggered by a commonly used word, they absolutely have my sympathies, but it is not a tenable policy to avoid perfectly commonplace language. For one thing, that sure is one slippery slope. Pretty soon you have nothing left but Newspeak.
If people do want to adopt such a policy then define a principle so that it can be applied consistently. I expect youâll have a hard time coming up with one that forbids âbrainwashedâ and doesnât take half of everything else with it.
Someone says âyouâve been brainwashed by Xâ, and I stop listening to them, because they are clearly conveying the idea that they donât believe I am capable of rational thought on the subject.
Thereâs a world of difference between, âHey mods, this guyâs using Forbidden Languageâ, and âIâd recommend avoiding this loaded termâ.
âDonât insult the people youâre trying to convinceâ is pretty much Communication 101
That said I understand that you arenât demanding, only offering advice. My point was that itâs poor advice.
Now thereâs a third thing you could say (besides for demanding or advising), which you alluded to now, namely requesting. If you would say, âplease donât use the word brainwash, it interferes with my ability to focusâ or something like that, I have no problem with that of course.
But it was certainly not intended to imply you were literally brainwashed and canât think rationally. If you read more if Som Snytt youâll see that his writings are about 70% humor and wordplay. Also note that he said âwe,â including himself (and most people). Thereâs something humorous about thinking about how constrained our thoughts really are, and about using exaggerated terms like âbrainwashedâ to wonder about the extent of our own biases.
nafg, I think Morgen wasnât making a comment about about his mental state. It seems to me that he was saying, âWhen you use âbrainwashedâ, it indicates a lack of respect for the person you are addressing, as well as suggesting that you donât intend to evaluate their arguments in good faith as you believe they are operating as if due to intentionally misleading psychological conditioning, not rational evaluation.â (Morgenâit wasnât very clear the first time because âheavily loaded termâ isnât explanation enough! Indeed, âloaded termâ is kind of a loaded term given its pejorative connotations. Best to avoid it in most cases and instead say what the problem is, donât you think? nafgânonetheless, your response the first time was kinda over-the-top!)
Morgen, nafgâs point about understanding the speaker a little better is very aproposâSom says all sorts of peculiar things that, taken together, add up to a quite amusing and often insightful whole; as with many things, if you cut out individual bits they can seem, isolated, a lot worse than they are.
</meta>
I prefer function-call-try to postfix-try because I tend to read code from top to bottom, and understanding what one needs to think about w.r.t. exceptions is information you want to have in advance. Hence, try should appear at the beginning to aid with documentation/code understanding.
We already have Try or try at the beginning, so I think everythingâs good as it stands.
I understand that and it would be true if Som had said âyou only think that because you are just brainwashed.â But in fact he said âwe are brainwashed.â Even if it was meant literally (and it should be obvious it was not) itâs not condescension when you include yourself. (It can be un-generous though.)
I donât really think that it is. Even without quiet control syntax, this is valid Scala 2 code:
Valid Scala code indeed, but it is not doing what I had in mind for match-with-catch:
e1 match e2 with catch e3
e3 would handle exceptions occurring in e1 , but not those in e2 .
This way
e2 handles the successful results of e1
e3 handles failures of e1
That is like the branching flow in if statements and in a futureâs onComplete method.
This would be problematic, because (as implied above by the note about try / Try non-equivalence) the current behavior of try and Future 's error handling are not equivalent.
I donât see how that would problematic in practice. I guess there would be a difference when an Error is thrown during the futureâs execution. What would be the difference between the match-with-catch version and the onComplete version?
try readList() catch {
case _: java.io.IOException => 3
case _: java.lang.Error => 4
} match {
case Nil => 1
case x :: xs => 2
}
Itâd be problematic because the Future is asynchronous, so if thereâs a try wrapping code which returns a Future, itâs because the failure can happen outside the Future context. By rewriting the try into the Future context, youâd lose the error handling put there to catch Exceptions which are known to be outside this context.
Itâs not great when it happens, but there has to be a way to deal with situations where creating the Future can fail before the Future is initialized.
Fair point, Iâll take care to be more explicit in the future. âBrainwashedâ is a complicated term, and I had hoped to avoid dealing with that complexity - a mistake on my part in retrospect.
@nafg, Iâm aware of what @som-snytt said, and youâll note that I ascribed no malice to him. Specifically, I described the chilling effect on discussion you get throwing around stuff like âbrainwashedâ, and was careful to use language that did not imply I was attempting to put that on his original usage.
To be plainly honest, I figured English was not his first language, and he was using a word he understood the definition of, but not the connotative baggage it carried. I wasnât even annoyed with him, I wanted to help him avoid putting his foot in his mouth - because I do that so often itâs hard to get the taste out.
If you want to avoid offending me, donât misrepresent what I say, because that did piss me off. Call me out if I say something stupid - because (Aspie that I am), sooner or later I will say something monumentally stupid, but stick to what I actually say. Lord knows youâll have no shortage of material.
I think Iâve said my piece. Responses should probably go to DM, to avoid cluttering the thread further