views:

1110

answers:

11

I frequently hear claims that Scala is much more "complex" than Java.

Can anyone therefore provide an example of Java code that can't be improved by writing it in Scala, or Scala code that can be improved by writing it in Java (but not by just rewriting within Scala)

By "improve", I mean that the code is better with regards to one (or more) of the following characteristics:

  • readability - how quickly can another developer, familiar with the language, understand the code
  • maintainability - how much work is involved in a simple refactoring
  • thread safety

... but doesn't sacrifice any of the above qualities.

It must be a plausible example, something that could potentially exist in a real program.

I also don't expect the API to match 100% after the transformation, and would prefer that Scala code sticks to Scala idioms, while Java sticks to Java idioms.

+5  A: 

No.

Tony Morris
? [ ](http://google.com)
Kobi
@Kobi: How did you do that? :-O
missingfaktor
That is besides the point. When did "no" became a valid answer with 10 votes?
Kobi
But if people insist on having my exploit fixed, it's `[ ](http://example.com)` - you could see the link if you used FireBug.
Kobi
@Missing Faktor, add a couple of **back-tick+space+back-tick**.
Bart Kiers
@Kobi, @Bart: Thanks!
missingfaktor
Not very helpful answer...
Tomas Narros
@Kobi It's valid, it answers the question that was asked, though probably not of much benefit to anyone else without a bit more explanation...
Kevin Wright
+4  A: 

The only examples I can think of where a pure Java implementation may be more concise than a Scala one is if you need to use a Java library, and don't want to write your own Scala wrapper around it. That said, there's nothing stopping you writing the same code in Scala.

Some examples from Progrmaming in Scala of why Scala is more concise than Java

Java

class MyClass {
    private int index;
    private String name;

    public MyClass(int index; String name) {
        this.index = index;
        this.name = name;
    }
}

Scala

 class MyClass(index: Int, name: String)

Java

boolean nameHasUpperCase = false;
for(int i =0; i < name.length(); ++i) {
    if (Character.isUpperCase(name.charAt(i))) {
        nameHasUpperCase = true;
        break;
    }
}

Scala

val nameHasUpperCase = name.exists(_.isUpperCase)

When it comes to thread safety the idea is that because Scala prefers objects with immutable state you can pass them to separate threads without worrying about concurrency. Its still possible to make non thread-safe Scala code using var instead of val

Jon Freedman
How so? You don't *need* to write a wrapper around Java APIs, it just usually makes sense to do so.
Kevin Wright
It was the only thing I could come up with other than *no*
Jon Freedman
+3  A: 

If you compare Scala type system with Java type system, Scala is more complex. This does not mean that Scala is less capable, but for a new developer Java will be easier to understand.

gpeche
In fact it means that Scala is *more* capable.
pelotom
Agree with @pelotom. See this recent thread for an example of what Java's type system cannot do but Scala's type system can: http://stackoverflow.com/questions/3709298/help-with-removing-code-duplication/3715347#3715347
missingfaktor
So Scala is more complex than Java for things that Java can't do? Okay...
Kevin Wright
I am not addressing what power the languages have. What I mean is that Scala richer type system often makes things harder to understand to a non expert human. It is similar to C++ templates: very powerful, you can do lots of things with them, etc., but template-less c++ is a lot easier on the eye.
gpeche
I'm still not convinced, some of the techniques available through Scala's type system seem to require unworkably long type signatures in Java, very heavy overloading, or hacks using reflection that totally obscure what you're trying to express. I don't believe that any of these techniques result in code that is less complex when it comes to understanding or maintaining it.
Kevin Wright
Not that I am trying to convince you, it is just that the mindsets are different: Java is a pretty straightforward language meant for the average developer, and Scala has more advanced features for the smarter guys. It is the typical imperative vs functional thing.
gpeche
+10  A: 

I guess Martin Odersky already answered your question putting it in slightly different terms.

Anyway just give a look at this code example of a calculator implemented with monads. Personally I took some days to completely understand how it works. I suppose I could have implemented the same in java with a far more verbose but also far more straightforward way.

I posted here my personal opinion about this question.

Mario Fusco
But this only shows that you lack the necessary theory (and I don’t blame you – so do I!), not that the code is complicated or less straightforward. That’s a bit like saying that building a modern car using 18th century tools is more straightforward because the tools were less sophisticated.
Konrad Rudolph
(After reading the article you linked, I think that you were already aware of what I said in the comment.)
Konrad Rudolph
Yes, I suppose we are saying the same thing.
Mario Fusco
The intent there was to demonstrate monads, surely it isn't the simplest way to implement a calculator in Scala :)
Kevin Wright
+9  A: 

Sorting a list of lists by their sizes, and then printing the result:

In Java,

@SuppressWarnings("unchecked")
List<List<Integer>> xss = Arrays.asList(
  Arrays.asList(2, 4, 5, 6),
  Arrays.asList(3, 6),
  Arrays.asList(78, 52, 11),
  Arrays.asList(9)
);
Collections.sort(xss, new Comparator<List<Integer>>() {
  @Override
  public int compare(List<Integer> x1, List<Integer> x2) {
    return x1.size() - x2.size();
  }
});
System.out.println(xss);

In Scala,

val xss = List(List(2, 4, 5, 6), List(3, 6), List(78, 52, 11), List(9))
println(xss.sortBy(_.size))

Clearly, Java is simpler than Scala! :P

Eric Grindt
That doesn't mean a lot. For example, by using lambdaj, you can sort the list with:sort(xss, on(List.class).size());That doesn't seem so different from the scala version.
Mario Fusco
Parity doesn't count, I'm looking for an example of Java being simpler than Scala, not equivalent for some trivial case.
Kevin Wright
Umm... Sarcasm?
one-zero-zero-one
That List class could be defined in Java too. Further; Java enables you to define a type (List<List<Integer>>) but does not requires that. The sortBy method uses fancy syntactic sugar to create an anonymous method. It's rather oblique but interresting. I can't really tell if its more or less complex than manually instantiate a wrapper class that implements the required function.
KarlP
List xss = new List( new List(2,3,4,5,6),new List( 3,6), new List( 78,52,11), new List(9)); System.out.println(xss.sortByMethod("size")); }
KarlP
There's a problem with that approach though, you run into the normal issues of dynamic typing/raw types, this variant would also compile: List xss = new List(new List(2,3,4,5,6), "some string", 96L, 4.3); System.out.println(xss.sortByMethod("size"))
Kevin Wright
@KarlP: The Scala example shown above is fully typesafe (The sophisticated type inference system makes type annotations unnecessary). The Java code you are showing is not typesafe as it uses raw types, and probably makes use of refection trickery.
missingfaktor
+4  A: 

Hmm, I can see this response getting lots of downvotes.

I believe the key really comes down to what you stated in the question :

How quickly can another developer, familiar with the language, understand the code

I think Scala's complexity portrays itself if the question was rephrased as

How quickly can another developer, unfamiliar with the language, become productive at writing code

In many ways Scala reminds me of C++. There's really tons of small (and big) things a developer needs to learn, practice and internalise before achieving any reasonable degree of competence with the language.

These are two completely different dimensions of measuring complexity. Not sure if other opinions on Scala's are driven by the same factors as those I described above.

Dhananjay Nene
The current figure being published by EPFL is that a Java developer can achieve the same level of productivity in Scala after 6 weeks, this based on the experiences of twitter and EDF trading.
Kevin Wright
Kevin, if you are referring to slide 55 of http://lamp.epfl.ch/~phaller/doc/scala-tutorial-sac2010.pdf then I've read it as 4-6 weeks for Ops not developers (not sure if thats the correct interpretation).
Dhananjay Nene
I am not sure what is the threshold benchmark to achieving same productivity is. In my mind it is where one can entrust a task to a new Scala developer with similar expectations and confidence as compared to those the developer could conduct himself with while earlier coding in Java. It is my *unscientific* belief this time is likely to be of the order of 4-6 months not 4-6 weeks. In addition I expect there to be some developers (at the lower end of the bell curve) who were productive on Java, to perhaps never quite make it with Scala.
Dhananjay Nene
This is measured experience of those who have made the transition. As a case study there's definitely room for improvement regarding application of the scientific method, but it's still a valid observed metric.
Kevin Wright
I voted you up. I think the C++ comparison is mostly valid...although C++ is growing so... There are a lot of developers out there working in Java or C# who never bother to fully understand those languages (C# is big these days, but I'm referring to its original state). These developers are not going to be successful with Scala. That's OK, it's debatable whether they are successful at what they do. But they have jobs and are paid decently, so one could argue they are successful.
Erik Engbrecht
That slide was 4-6 weeks for developers. The reference to ops was stating that they don't see any difference at all, Scala is just another jar.
Kevin Wright
+1  A: 

I think you're mixing two things in your question.

Scala is much richer in features than Java (thus the language is more complex), but that allows the programmer to write more concise and expressive code most of the time (thus the resulting programs are simpler).

fortran
I'm not convinced here. Scala *removes* a lot from Java, such as primitives, operators and other syntactic restrictions. If anything, Java is richer in special-case features (such as the ?:) operator, but Scala's reduced feature set is more general purpose and easily combined. An analogy with CISC/RISC instruction sets would be appropriate here.
Kevin Wright
I've never programmed in Scala (just read a few tutorials) so probably I don't know even half of the features, but just with higher order functions, pattern matching and mixins it seems much richer than Java.
fortran
Anyway, following your CISC/RISC analogy, having many different ways to achieve the same thing with subtle differences (say, being able to add operands in register, in memory directly addressed, or in memory addressed by a register and an offset, etc.) doesn't make the feature set richer, because the feature is the same (add two numbers), instead, having fundamentally different capabilities (e.g. add, substract, multiply, divide, n-root, logarithm, etc.) is what makes a certain feature set richer than other (not just denser).
fortran
Scala was able to remove massive chucks of special-behaviour when compared to the Java spec. For an example just consider all the rules for coercing types when appending objects/primitives to a string. Likewise, a trait can just be seen as an interface, without the restriction that all methods must be abstract.
Kevin Wright
Those are really just pushing complexity around. The coercing rules from object/primitives to strings what pushed from the language into the standard library. That's good, but from a user perspective it doesn't make much of a difference whether the magic is in the language or the standard library. I think seeing traits as interfaces is dangerous, because interfaces provide a very small subset of what traits provide.
Erik Engbrecht
+2  A: 

There is just one case that I've encountered where a Java->Scala translation can be difficult.

Scala requires that all classes have a primary constructor, any other constructors must ultimately delegate to the primary.

This can cause an issue when attempting to convert a Java class that has multiple constructors which don't interact with each other. Having said all of that, the design pattern is invariably a code smell in Java.

so I can't claim in good conscience that this Java pattern is simpler than the corresponding Scala pattern, not when it should never pass a code review in the first place!

Kevin Wright
+5  A: 

Prior to working in Scala I never had to:

  1. Disassemble my own code to figure out what was going on in order to diagnose bugs
  2. Spend hours (or days) tweaking JVM parameters and reading arcane JVM documentation
  3. Scala has made me thankful that HotSpot is open source, not for the community reasons, but so that I could look at the source to help diagnose problems with my programs.

So ironically I've found that working in Scala, which is a much higher-level language than Java, has forced me to be far more aware of lower-level details about the compiler and the JVM. Not that this interferes with writing Scala or that I even mind it. It was just a learning curve I had to climb, and I personally enjoyed it.

I'm also not claiming that my experience is typical. I don't shy away from low-level details, and usually avoid magic (or, rather, learn enough such that I don't consider it magic anymore). For example, in order to comfortably transition from C++ to Java, I had to read papers on GC algorithms. Not because I had problems with Java's GC, but because treating it as magic just felt so wrong. So you could say I'm neurotic. But I think it's helped me debug and tune Scala code on many occasions.

Overall, I would say Scala, and especially some idiomatic patterns in Scala, tend to greatly obfuscate what the code is doing in favor of the intent of the code. 95% of the time that's a great trade. But that remaining 5% can be a real drag.

Erik Engbrecht
I love the last paragraph, though I'd say that's true about pretty much all high-level languages.
dsimcha
Yup, it is. There's really two questions relating to it: Is it really 5%, or is it more or less? How bad is the drag? The drag with Scala isn't that bad if you understand it enough to figure out what's going on under-the-hood. But if you pretend none of the abstractions ever leak, well....
Erik Engbrecht
+6  A: 

The only case I know of is when you have the additional demand of performance; here's the already-properly-written Java code (I don't see the point in starting with poorly written Java and making it better, but I can always use some other less-suitable loop construct):

// Java (fast)
public double maxsum(double[] x, double[] y) {
  double sum = 0.0;
  for (int i = 0; i < x.length ; i++) sum += (x[i]>y[i]) ? x[i] : y[i];
  return sum;
}

In contrast:

// Scala (fast)
def maxsum(x: Array[Double], y: Array[Double]) = {
  var sum = 0.0
  var i = 0
  while (i < x.length) {
    sum += if (x(i) > y(i)) x(i) else y(i)
    i += 1
  }
  sum
}

In this particular case, Scala has less compact syntax (Array[Double] vs. double[]), a less powerful looping construct with more chance for error (the index variable floats around on three separate lines), and a less compact alternate-assignment (if/else vs. ?:) that clutters the code unnecessarily.

There are compact ways to do this in Scala:

// Scala (slow)
def maxsum(x: Array[Double], y: Array[Double]) = (x,y).zipped.map(_ max _).sum

but this rewrite is unhelpful if you want the result computed quickly (i.e. at C speeds). If, in contrast, you want to write the code quickly and your performance bottleneck is elsewhere, this is an improvement.

Edit: I managed to get the inequality backwards the first time. It's fixed now, but it does highlight how nice it would be if the "slow" Scala version performed as well as the "fast" one....

Rex Kerr
I conspicuously left out performance, because it's such a slippery thing to pin down (unless using a profiler with suitably warmed code on your target hardware platform). Even with a simple example like this where the performance benefit seems obvious, an imperative design is going to perform worse than a declarative solution able to make use of multiple cores or offload work to a GPU. You get an upvote anyway for raising a valid point.
Kevin Wright
+1, First post that actually answers the question.
missingfaktor
@Kevin - Scala's declarative solution doesn't _yet_ automatically use multiple cores, and sometimes speed is a necessary part of a solution--too late can be as bad as not at all. So I see your point, and hope eventually my later example will run faster than the former (if I have cores/GPU to spare), but for now the examples I've shown above impact a non-negligible number of Scala coders.
Rex Kerr
+1  A: 

Sure. Here:

// Scala
val sum = (0.0 /: l)(_ + _)

// Java
double sum = 0.0;
for (int i = 0; i < l.length; i++) {
  sum = sum + l[i];
} 

Of course, the Scala code could be written to look just like the Java code, but that's irrelevant to Joe Enterprise. All Joe Enterprise cares about is that he is trying to fix or add a feature to some code through which dozens of different programmers have gone before, and which does contain that line.

Those dozens of other programmers may perpetrate all sorts of absurdities in the code, but at least it is always pretty clear what the code is doing (as long as one ignores the perils of mutability) in Java, where the same cannot be said about Scala.

Not that I in any way agree with that notion. I think one should be an expert in whatever language one is a professional programmer for. You wouldn't want a contractor who knows "more or less" how to use his tools, right?

Daniel
There's an important distinction here that is often blurred. It is very clear exactly what the Java code is *doing*. The Scala code (which I think is incorrect, but I'll ignore that for now...) it is more clear what it is accomplishing (assuming you understand folds), but how it is doing it is highly opaque.
Erik Engbrecht
@Erik Scala code seems correct to me. Anyway, I used fold just as an example, but if I replace `/:` with something else, do you know if `_ + _` is a parameter to an `apply` or a second parameter list? Do you know if there is any implicit conversion going on? Many different things could be going on, with the very same code.
Daniel
@Daniel - oh, sorry, I mistook the lowercase l for a number 1.
Erik Engbrecht