I like break and continue. Do we really have to jump through hoops to avoid them just because some grandfather stated "goto considered harmful" sometime in the last century?
No, if goto is really important to you, you can keep using Java (which was made sometime in the last century). You'd only use Scala if you thought that the language was created by smart people who have made the correct decisions with their language's feature set.
I agree. There are cases were break and continue are much more succinct and easier to understand, just as there are with goto (error handling in C for example, see linux kernel). To get rid of them just because someone considers it harmful is stupid. I'd guess the reason Scala got rid of them is not because they're harmful but because they're not very useful in a functional language where you usually don't deal with imperative loops.
I could probably live without "break", but "continue" is very useful.
for(Person p: persons) {
if(p.getAge() < 18)
continue;
// lines of code here
}
The alternative is to have a if-else instead, and that hurts readability even if you don't usually have much code inside a for-loop. You could probably also solve it by writing a filter function that generates a new list with those you want to process, but I find having lots of "magic" functions scattered around the code to be just as annoying. And it will also hurt performance / memory usage for large datasets
Unless you have multiple of these conditional checks when the indention level gets unholy.
Continue in loop is like early return from a function. Some say we should not use it. But other find it really painful to work without 'continue'. I remember moving whole body of a loop into a function call only to get "continue" support in Lua though early return.
Honestly, the exact example they criticise is a common device I use to make code less complex. Yes, you can horribly mis-use it, and you can horribly mis-use goto, but I don't want someone to tell me I can't use something just because I might not use it properly. There's an interesting discussion on goto's use in the Linux kernel here: http://kerneltrap.org/node/553/2131 (the final example, stack-style rewind, is NOT pretty in Java).
You can break in Scala by encapsulating a code block within a 'breakable {...}' scope. The break throws an exception caught by breakable; the break literal though is not a keyword. Odersky explains (section 7.6) that because Scala leans toward a functional rather than imperative paradigm, it was necessary to give up traditional break & continue in order to incorporate other functional language facilities. He poses: what would 'continue' mean within a function literal? Reading Odersky's book now... it's interesting stuff.
You mean Dijkstra [1]? The guy who figured out shortest-path-first routing algorithm, semaphores, reverse polish notation?
The reason GOTO considered harmful (read the paper) was to assist in formally verifying the semantics of programs. Essentially, GOTO constructs fork environments in the formal analysis, and make things really difficult to work with.
They also make informal reasoning more difficult unless you apply restrictions on how you structure your program.
Know your history before you insult the people who came up with principles.
The article suggests as a replacement for break "but generally extracting a loop to a separate method/function (or at least putting it at the end of existing method) and using return instead will do the trick"
return (from anywhere but the end of a function) is just as damaging to formal verifiability as continue, break or goto.
Continue, break, return at least are well-formed with respect to the local environment.
GOTO has no such restrictions (well, in older languages allowing arbitrary GOTOs)... that's why its considered harmful.
The single-return principle is used for flowcharts & formal analysis ease.
It'd be mildly interesting to do a retrospective of compilation & static analysis algorithms to see what more current research turns up with respect to the single-return rule's use.
Didn't know it was Dijkstra and didn't actually mean to insult anybody. I thought the 'GOTO' thing was just a community opinion that emerged sometime in the last century.
Anyway, I still think break and continue are OK. Maybe they are not as bad as GOTO, and also I never run into problems with verification of my code.
I agree regarding the rant. I want an explanation of why I no longer need those constructs in Scala, not just a hand-wavy "they're bad, stop using them". Currently I need them, telling me that I do not is not going to sway me to your cause!
Yes, his silly "hands up if you find this more readable" breaks down if you now have two checks at the beginning, and the "rest()" part carries on for more than one line. Then you're carrying around two extra levels of indentation and cognitive context, for what exactly?
"Why do we have a special syntax for arrays in the language while collections are implemented in on top of the language? And isn't a bit irritating to convert them from one to another all the time?"
Perhaps it's just me, but I do not convert collections to arrays "all the time". I can't remember the last time I did so. It seems that the author has some bad experiences with certain libraries, but he shouldn't assume that it is part of the standard java experience.
The devil's advocate argument is that it isn't readily apparent that you're using the ages array until you look deep inside the loop. With the scala code, especially with the functional syntax, you know what elements you're working with right up front.
Java and the JVM are not the same thing. Java is a programming language. The JVM is a stack-based virtual machine that executes Java bytecode. Java bytecode is what Java compiles into (ie. the contents of .class files).
As it happens, the JVM can't tell if a .class file was generated from compiling Java code, or handwritten, or generated from another programming language altogether. As long as the class file is valid, the JVM will run it. In the case of Scala, "continue" isn't in the language, so bytecode that performs the operation is never generated by scalac. In fact, "break" and "continue" don't even have any meaning at the JVM level. Java bytecode works at the level of gotos and conditional branches.
I do the same; it more clearly shows intent IMO. I think your second example is more ubiquitous because of the teaching that "jumps" are bad; break, continue, goto... all of them bad. Don't do that. Etc.
Where I use this pattern a lot is argument validation on the tops of method bodies. And sometimes, "avoid the impossible conditions early" rule
To me, the odd thing is that it doesn't mention the one thing Scala drops for which I haven't a workaround: static final fields. Now, from a pure coding standpoint, I don't actually need a static final field. However, Android requires such creatures if you want to create a new Parcelable, Android's lightweight alternative to Serializable.
33 comments
[ 2.9 ms ] story [ 62.4 ms ] threadContinue in loop is like early return from a function. Some say we should not use it. But other find it really painful to work without 'continue'. I remember moving whole body of a loop into a function call only to get "continue" support in Lua though early return.
Basically it all comes down to organizing code. Removing 'continue' removes one's ability to organize code in a good way, as some see it.
persons.filter(_.age >= 18).foreach(p => { (code here) });
That is way, way more readable, imho.
The reason GOTO considered harmful (read the paper) was to assist in formally verifying the semantics of programs. Essentially, GOTO constructs fork environments in the formal analysis, and make things really difficult to work with.
They also make informal reasoning more difficult unless you apply restrictions on how you structure your program.
Know your history before you insult the people who came up with principles.
https://secure.wikimedia.org/wikipedia/en/wiki/Edsger_W._Dij...
return (from anywhere but the end of a function) is just as damaging to formal verifiability as continue, break or goto.
Continue, break, return at least are well-formed with respect to the local environment.
GOTO has no such restrictions (well, in older languages allowing arbitrary GOTOs)... that's why its considered harmful.
The single-return principle is used for flowcharts & formal analysis ease.
It'd be mildly interesting to do a retrospective of compilation & static analysis algorithms to see what more current research turns up with respect to the single-return rule's use.
Anyway, I still think break and continue are OK. Maybe they are not as bad as GOTO, and also I never run into problems with verification of my code.
This guy cannot be a good programmer.
Perhaps it's just me, but I do not convert collections to arrays "all the time". I can't remember the last time I did so. It seems that the author has some bad experiences with certain libraries, but he shouldn't assume that it is part of the standard java experience.
I also don't see why this:
is "surprisingly tough to implement cleanly" compared to: The second syntax may be clear to Scala programmers, but I think the Java version can be understood by most programmers[edit: fix syntax]
http://www.scala-lang.org/node/257
I think this makes sense. Both encourage bad habits but continue is very easy to emulate and break is not always easy to emulate.
edit - clarity
As it happens, the JVM can't tell if a .class file was generated from compiling Java code, or handwritten, or generated from another programming language altogether. As long as the class file is valid, the JVM will run it. In the case of Scala, "continue" isn't in the language, so bytecode that performs the operation is never generated by scalac. In fact, "break" and "continue" don't even have any meaning at the JVM level. Java bytecode works at the level of gotos and conditional branches.
1) reduced nesting in the first,
2) makes it more clear that unusual condition should simply be skipped.
Is this a personal style thing, or should is it generally preferred to do the second option?
[1] http://metaphysicaldeveloper.wordpress.com/2009/05/02/closur...
Where I use this pattern a lot is argument validation on the tops of method bodies. And sometimes, "avoid the impossible conditions early" rule