Scala 2.10 now available
scala-lang.org
scala-lang.org
The biggest addition is macro support, which allows compile-time metaprogramming and code generation. This brings the ability to write very dynamic-looking code that is in fact completely type-safe. These capabilities have been used to great effect by Slick (a new database library based on ScalaQuery), ScalaMock, and others. Right now the tooling support for writing macros is a bit weak, but I expect it to improve now that 2.10 has been released.
There's a lot else to like here, with built-in futures and promises from Akka, string interpolation, reflection, and a bunch of speed improvements and bug fixes.
It's great work by the Scala team, and an exciting start to a new year!
It's worth mentioning that Slick is a lot like .NET's LINQ to SQL.
On one hand I was really impressed by its capabilities, on the other hand the documentation is unfortunately lacking...
I think Slick has great potential and hope that typesafe brings the documentation onto a quality level similar to Play. If you want to try it out today and get stuck, after some time I found it quicker to look at their test cases first before googling, much more info there than in the docu and example projects.
All in all, exciting times ahead.
Personally I got the "doomsday" offer which had a huge discount for IntelliJ IDEA Ultimate. And in my opinion, this IDE is worth every penny and I'm sad that I've stuck with Eclipse when I was working on Java projects.
To be back on topic, I had a very similar experience after using Eclipse for several years. A co-worker introduced me to IntelliJ in 2005, and I have not regretted the decision since. IntelliJ is a fantastic IDE, particularly for Java.
I found that it had feature parity with Eclipse for the most part, but there was enough missing that I went back to Eclipse. Time to donate!
A minor thing, sure, and there are ways around it, but the Eclipse Scala IDE found all classes. I have gripes about Eclipse as well, but nothing is perfect.
I also use Eclipse for C/C++ but I run a separate instance for C/C++ so using IntelliJ wasn't an issue.
For my workflow IntelliJ didn't seem to add anything, but it did take away one or two small things.
"For Akka users this change does not have visible effects (you will continue to depend on the same artifacts)" http://letitcrash.com/post/37716546018/2-1-spotlight-akka-ac...
Use "sbt ~compile" or "sbt ~test". IntelliJ 12 + Scala plugin even an external running sbt incremental compiler to do compilation for the IDE.
I have 2 scala programs in production, one of which also has one java file (merssenetwister inlined) and I deploy incrementally built jars without any problems so far.
What scala+sbt versions (or whatever) do you use?
(editted formatting)
Class A contains public static final String x = "x"
Class B contains public static final String y = A.x
Class A modified, A.x = B.y
Result: A.x and B.y = "x"
clean and compile, no code changes
Result: A.x and B.y = null
The reason this occurs is because information is lost during compile. The compiler optimizes the references away and doesn't fix them w/incremental an compile. This occurs in both sbt referencing javac and the eclipse incremental compiler in Eclipse IDE.
While this is contrived, the main point is that more complex interactions occur where these references may not be updated properly and you may end up with behavior you were not expecting due to these optimizations. Interestingly, I think the problem can be solved if the compiler were to keep incremental metadata explicitly stating where these dependencies exist. This certainly is the case with eclipse, where the IDE knows about the link, but still produces behavior that is dependent on compile order and not on the code change itself.
Thanks for taking the time to make and example.
The Scala team knows compilation speed is important; they have dedicated people working on it full time. This release they made progress by creating an incremental compilation system called Zinc that is shared by Eclipse, maven, and most recently, IntelliJ. They have also said that there is no easy fix on the horizon. Improvements will take time and likely continue to be incremental in the near future.
The reason they built their own is because they need more data about the compilation process than Zinc provides.
It would have been more accurate for me to say that this release the Scala team developed an SBT incremental compiler that is used by Eclipse, Maven, and, most recently, IntelliJ.
I hope that they don't fall into the trap that the Mozilla folk have with Firefox. Although Firefox is still slow, it isn't as bad as it once was. Even after substantial effort and some moderate improvements, it still has a very bad reputation. I don't think it'll ever overcome this.
The same could easily happen to Scala, if they aren't careful.
If you have a 2000-file program with cyclical dependencies you are screwed. If you use Scala-IDE (which has an embedded sbt doing incremental compiles, which become non-incremental if your dependency structure is fail and you have a huge SCC) on such a project you are doubly screwed. That's not a problem with Scala. Bigass programs aren't a good idea in any language. The programmer-to-program relationship should be one-to-many (for engagement, productivity, modularity, code quality) and not the "enterprise" reverse.
If you don't want a cutting-edge, powerful static type system there's an awesome JVM Lisp (Clojure) that I recommend highly.
Anyway, type-checking is probably the fastest part of compilation so there's no reason to give up Hindley-Milner for speed reasons. (One of the best features of GHC is that you can use GHCi to typecheck)
What Ocaml does really well, compared to both Haskell and Scala is type-inference, but it's kind of a weak language IMHO as far as functional programming is concerned.
I also don't get all this complaining, because in practice Scala compilation speed is not a problem. After working with Scala in production for a couple of months now, I'm beginning to suspect that all this is just hyperbole perpetuated by people that never worked with Scala a single day in their lives.
Admittedly, we do make heavy use of the type system.
Incremental compilation suffers from the fragile base class problem. In a well structured app with proper encapsulation and rigid (and type annotated) interfaces, it helps a lot.
The project I'm working on right now is about 15kloc, but it's split in 3 sub-projects. Coupled with incremental (and continuous) compilation, this compilation speed issue hasn't been a problem for me.
Also, if you look around, many open-source projects built with Scala follow the same technique. It's quite sane too.
For example, if you delete AbstractFooBase.unusedMethod, sbt will recompile every file everywhere that references a concrete Foo instance.
(In principle it should only need to recompile files which reference unusedMethod, but it's not that smart yet.)
* Launching the interpreter takes 10 seconds; 50 times slower than Haskell.
* Compiling a small module takes 15 seconds; 10 times slower than Haskell.
* Running 100 command-line unit tests on a small compiled module takes 1.5 minutes; 100 times slower than Haskell.
I also found Scala's type system requires many type annotations even in trivial code. For example, here Scala fails to infer the type of `optBar`, apparently because `None` is also a type:
scala> class Foo {
| def setBar(bar: Int) = optBar = Some(bar)
| def getBar = optBar.get
| var optBar = None
| }
<console>:8: error: type mismatch;
found : Some[Int]
required: object None
def setBar(bar: Int) = optBar = Some(bar)
^
Workaround: scala> class Foo {
| def setBar(bar: Int) = optBar = Some(bar)
| def getBar = optBar.get
| var optBar: Option[Int] = None
| }
defined class Foo
Moreover, Scala's implicits can pose a significant barrier to understanding other people's code.While OCaml's type system may not integrate objects cleanly, in everyday use type annotations are not necessary, perhaps because objects aren't commonly used.
Similarly, while it's possible to confuse Haskell's type inference by using advanced language extensions, in everyday use one tends not to run into such problems.
With SBT you're only going to do that once per work session. Plus the startup time isn't as bad as you make it sound. I've had a much more painful experience with Ruby (Rails).
> Compiling a small module takes 15 seconds
That hasn't been my experience. I just did a test for a project of mine and it took 5 seconds. Without line-counts such metrics are useless (how small is that module anyway?). Also many Scala projects are composed of multiple subprojects that are efficiently managed by SBT, so a root compile triggers compilation for all these sub-modules, but context-switching between them is what increases compilation cost.
> Running 100 command-line unit tests on a small compiled module
When in the world are you ever going to do that? Like seriously?
> Scala fails to infer the type of `optBar`
In practice it's good to annotate the signature of public functions. Haskell developers do that too, because really, when a developer looks at the definition of "optBar" are you seriously going to suggest that they should be looking at other parts of the code to infer what it returns?
IMHO, this is a feature, as what you want is even worse than what you get with a dynamic language, but YMMV.
> Scala's implicits can pose a significant barrier to understanding other people's code
I haven't met a single library or project of significant size that isn't making use of implicits in one form or another. Whether they are called global state, singletons or parameters injected through DI, we are really talking about implicit parameters.
The difference is that Scala gives you the means to document these implicits in the signature (referential transparency FTW). They are also statically type-safe, can be overridden and have the extra benefit that they make possible some powerful techniques, like type-classes, something that Ocaml isn't capable of.
> I just did a test for a project of mine and it took 5 seconds. Without line-counts such metrics are useless (how small is that module anyway?).
Obviously, comparing absolute times between two unknown systems isn't going to make sense. I was comparing how long it takes to accomplish the same thing on my machine in Haskell and Scala.
> In practice it's good to annotate the signature of public functions. Haskell developers do that too, because really, when a developer looks at the definition of "optBar" are you seriously going to suggest that they should be looking at other parts of the code to infer what it returns?
I agree, annotating type signatures of top-level functions is a good practice. However, in the above example `optBar` is an internal variable in class `Foo`. The point here is I found Scala's type inference to be incapable of dealing even with trivial code.
> The difference is that Scala gives you the means to document these implicits in the signature (referential transparency FTW). They are also statically type-safe, can be overridden and have the extra benefit that they make possible some powerful techniques, like type-classes, something that Ocaml isn't capable of.
Haskell does type classes without the need for implicits. Also, true referential transparency requires control over side effects, which is something neither OCaml or Scala are capable of, but Haskell is.
If you really think about it, type-classes are all about passing around a global vtable implicitly. If anything, Scala's implicits are a superset of Haskell's type-classes and allows for techniques that Haskell isn't capable of.
We could debate all day about what's better. If you're going to make the case that Haskell's type-classes are easier to reason about, then I can make the case that a dynamic language beats Haskell on reasoning about it any day of the week. In the end it's all about tradeoffs.
> true referential transparency requires control over side effects, which is something neither OCaml or Scala are capable of, but Haskell is
With all due respect, that's just bullshit. First of all because there is no such thing as "true referential transparency", second because most techniques that are available in Haskell for dealing with side-effects are also available in Scala. As examples, Scala's library is filled with monadic types and the Play framework makes use of Iteratees for composing HTTP responses, something which makes Comet/WebSocket a peach to deal with.
A referentially transparent expression is guaranteed not to have side effects. A Haskell function which doesn't advertise in its type that it may have side effects, by being in the IO monad, can be trusted to be referentially transparent. This cannot be said about OCaml or Scala functions.
First, I'm not a Haskell expert, but from what I understand there are no vtable passed around nor attached to "objects" in Haskell.
Type-classes are used to find an implementation given an instance. Without extensions you cannot do this:
> lst :: Show a => [a]
> lst = [1, "hello"]
So Haskell isn't the slightest dynamic here.
Both Haskell and Scala have some excellent work behind them, but they were built under different constraints.
See: http://c2.com/cgi/wiki?ConservationOfComplexity
Ultimately, the baseline requirements drive the minimal complexity of code. Sure a poor programmer can drive up the complexity with unnecessary constructs, but the converse is not true: a great programmer can drive to simplicity. For example, a flight control system for a 777 can never be reduced to a single file of 700 lines of code. It will likely always be 2000+ files, and have lots of inter-dependencies.
So I guess (run time safety issues of Scala aside) Scala is not an appropriate language for complex problems by your own words?
You mentioned flight control systems: those are unlikely to be written in Scala, being real-time systems, but if one were, it would not need to be compiled and recompiled on the fly.
Scala's a great language but it's not the right language for every problem. No language is.
For many large, non-trivial systems have several requirements: - tends to have complex dependencies - needs fast builds
This was a classic: http://www.amazon.com/Large-Scale-Software-Design-John-Lakos...
Essentially how to design C++ systems so that incremental compiles don't sink you. Developer productivity is important.
Scala is badly failing on this front IMO, it reminds me of the old bad days of C++ in a major way.
Maybe I've waited too long too many times for gcc to compile C/C++ that when I went to Scala I thought waiting some seconds to compile is okay =P
So, if you are making useless types, the speed concern is likely best addressed by moving stuff out of the type system. If the extra time is preventing bugs, then few would argue it is wasted.
Or am I completely off in my view?
So is GHC's. Turing-Completeness says nothing about speed, only about termination prediction. GHCi can type check most codebases in much less than a second. The puzzling thing about the apologism for Scala's slow speed is that some people seem to think that no FP language has ever had a fast compiler before...
Clearly, since my point was easily shown as a non-sequitor, I'm not an expert. Following the folks involved with Scala, on the other hand, I don't have any reason to feel that they are the rank amateurs that they would have to be to be to produce such a slow compiler with no need.
My hunch, the support of nominative subtyping is the culprit. My backing for this? Pretty much nothing other than snippets of posts others have made.
BTW, off topic but I would really recommend Odersky's class if it is offered again. I mostly use Clojure now, but the material in the class was generally useful for doing functional programming.
1) Code that is lumped into one gigantic JAR instead of being broken down into several different libraries that can be compiled faster.
2) Code that forces the compiler to "solve" many problems in the type system, such as recursion and many other powerful type level constraints.
The first isn't a problem with the compiler, it's a problem with how you're laying out your code. Luckily we don't have this problem.
The second is a problem if you've decided to use a lot of type level programming all over the place. I can't say if this is really a "problem" or not because it depends on your use case.
Following that advice will drastically speed up your compile time while working (obviously, a clean compile will take as long as ever).