The Scala ecosystem has been a topic of debates for years. Is it good or bad? Is it too small or too complicated? I think that the problem here stems from the fact that Scala as a programming language appeals to different categories of developers. Moreover, there is a common belief that Scala can be used either as "a better Java" or as "a Haskell for the JVM". In my opinion, this statement holds some truth, but it is a dangerous simplification which may lead to wrong conclusions.
A better Java
The fact that Scala runs on the JVM makes it relatively easy (at least in theory) for Java teams to adopt the more advanced language. Java libraries are still very useful and if you look at, say, Play internals, you will see a lot of old friends: Jackson, Logback, JodaTime etc. It makes perfect sense: if something works well, there is no need to re-invent the wheel. On the other hand, the Scala ecosystem has become so big that recently established Scala Center makes building a library index one of their primary tasks.
All thing considered, Scala is definitely a better choice than Java for most projects, and indeed, many developers, especially in the past, started using it as a Java without semicolons. This, however, is no longer the case and even when people start using Scala as a semicolon-free version of Java, they rarely stop there. Engineers eventually want more and start using more advanced features. As I pointed out in one of my previous articles, this is totally OK. Contrary to popular belief, Scala is not hard to learn and the most commonly used constructs could be explained in about 30 pages. This, I would argue, is a reason why Scala is getting popular among Ruby (Twitter, SoundCloud) or PHP (Tumblr) developers and why it is not limited to former Java gurus.
The interesting thing is that most former Java/Ruby/PHP devs are not interested in functional programming per se. However, functional features in Scala immediately make you so productive that it creates a great incentive to learn them rather sooner than later.
There are also some people who view Scala as a way to write Haskell-like code on the JVM. Often they are also very good at category theory and sometimes interested in languages even more exotic than Haskell itself.
For many of them, Scala is not an advanced language and in fact, it quite often doesn't live up to their expectations. In order to overcome some of its problems, they build new libraries, which often include alternatives to the standard library types), fix bugs in the compiler and make the language better.
Right now, there are quite a few projects consolidated under the Typelevel umbrella. They include cats (category theory abstractions), http4s (HTTP library), monix (asynchronous programming), doobie (database access), fs2 (a streaming library formerly known as scalaz-stream) and many others. These projects are built with functional purity in mind and have some other similarities.
For years, the most common advice for beginners has been "to stay away from ScalaZ stuff". Indeed, for a newbie, aiming at functional purity can be overwhelming and quite often its usefulness is not immediately obvious. However, after about a year of using Scala, people start to understand that actually ScalaZ is not that scary and provides very useful abstractions for many use cases.
A model example - error handling
Let's talk about one specific example - error handling.
One of often criticized Java features is so-called checked exceptions. In my opinion, by introducing checked exceptions Java solved many problems, but introduced several others. On one hand, defining a method as throwing exceptions is a good way to communicate to users about possible dangers and it is obviously a huge improvement over using a global variable containing the error code. On the other hand, throwing exceptions distort the normal flow of the program and wrapping them in a try blocks becomes mundane very fast. Defining all possible errors as
RuntimeExceptions is hardly a solution, because it solves the latter but not the former.
In Scala, you can always resort to
try blocks, but there are simpler and better ways to work with dangerous code. In particular, the 2.10 release introduced a new type called
scala.util.Try, which provides a sane way to handling errors and works well in many cases.
Try is not perfect, though. In particular, it encourages the use of
Throwable, while you may want to use your own exception subclasses for better type-safety. In this case, you may look at ScalaZ disjunctions (written as
\/) and find out that this is an extremely powerful abstraction, which comes with a lot of additional goodies. For example, disjunctions provide a conversion for converting a list of disjunctions to a disjunction of a list and also simplify working with
I believe that Scala hits the sweet spot by throwing into the mix pragmatic developers, who simply want to get things done, and academia experts, who drive the progress further. Essentially, it means that from an end user perspective, there are usually at least three options to solve their problem:
- use a Java-inspired approach or library (without semicolons, of course!)
- use a Scala library (or framework), which uses some functional features therefore making your code more clear and concise. Examples include abstractions from the standard library, Play, Akka, ScalikeJDBC and many others
- use a Typelevel project such as Doobie, Argonaut or ScalaZ.
I don't know of any other language that gives similar choices. Probably, this is the very advantage that allows Scala to spread and grow without showing a single sign of stagnation (for more information see my previous post - Analyzing Scala popularity).
Finally, if you think that Scala is worth learning and want to make this process very efficient, take a look at my previous post about learning Scala.