What features of Java have been dropped in Scala?
javacodegeeks.com
javacodegeeks.com
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:
for(int idx = 0; idx < names.length; ++idx)
System.out.println(names[idx] + ": " + ages[idx]);
}
is "surprisingly tough to implement cleanly" compared to: names zip ages foreach {p => println(p._1 + ": " + p._2)}
The second syntax may be clear to Scala programmers, but I think the Java version can be understood by most programmers names zip ages foreach { (name, age) =>
println(name + ": " + age)
}
which, imho, is a little easier on the eyes.[edit: fix syntax]
a b c d e f g
becomes: a.b(c).d(e).f(g) zipWith (\x y-> x ++ " : " ++ show y) names agesThe 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.
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 for (p <- persons; if p.getAge >= 18) {
println(p);
}persons.filter(_.age >= 18).foreach(p => { (code here) });
That is way, way more readable, imho.
for(Person p: persons) {
if(p.getAge() >= 18)
// lines of code here
}
If anything, I would argue that this version is clearer since it makes the context of execution more explicit.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.
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.
foreach(x in list)
if(unusual_condition(x))
continue
x2=perform_data_transformation(x);
x3=perform_data_transformation(x2);
to foreach(x in list)
if(!unusual_condition(x))
x2=perform_data_transformation(x);
x3=perform_data_transformation(x2);
Because1) 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?
foreach(x in list.reject(unusual_condition(_)))
x2=perform_data_transformation(x);
x3=perform_data_transformation(x2);
I find collections and their functional methods are great for clear expression of intent[1][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
if (something_bad)
return
do_good_stuff()
...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
This guy cannot be a good programmer.
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.