Some thoughts: I've worked on several large scala projects, and I've found that long incremental compile times are often a sign of bad encapsulation. If you change the type signature of a public method then any file using that class needs to be recompiled.
I've found that explicit type annotations on method return types help a lot here:
This has type `BanditRef => ConcreteSimpleBandit`. If I change the implementation and return a ConcreteNonSimpleBandit, the inferred type signature changes to `BanditRef => ConcreteNonSimpleBandit`. If I use an if-statement and return one or the other, the return type will be the nearest superclass of both (say a ConcreteBandit).
However, if I explicitly annotate it to return a BanditLike
then only the class in question needs to be recompiled.
The author is spot on about the use of infix methods. These are nearly always evil. What would be great if Scala gave you a way to explicitly declare certain functions as infix, and everything else uses the java-style calling convention. For a monoid, a |+| b |+| c makes perfect sense. However, consider:
Having worked with both Scala and C++, I actually think that people saying this don't know what they are talking about.
I encourage you to take another look, as we often jump to criticisms with only a superficial understanding, often based on comments made on forums by other people. In particular, the idea of writing the code in a certain way to avoid recompilation is rather silly and I never, ever did it in the last 2 years since I worked with Scala.
On syntax and complex language features - having trained rookies unfamiliar with Scala myself, I can tell you - it's neither the syntax or the language features that are problematic, but rather the concepts involved. The Scala ecosystem is chock-full of paradigms coming from static FP languages such as Haskell. Scala's features are actually very elegant and orthogonal. It does have ugly corners that are a result of its interoperability with its host, the JVM, but that's a tradeoff I like, because people that don't like the JVM, haven't seen what it can do.
On compilation speed, it's not much of a problem though I understand why people don't like it. But the type system is very static - and in comparison with Java in which the type system does nothing else but to stay in your way - in Scala it actually helps you to write code that is sometimes provably correct or to design safe and user-friendly APIs. For me it's not a problem if my code takes an extra couple of seconds to compile, because the compiler does help me in the case of Scala. In terms of recent developments, both SBT and Maven are doing incremental compilation. Plus, SBT makes it really, really easy to break your project into multiple sub-projects that depend on each other, to keep them small, something which helps with compilation speed though personally I do it for keeping the code base cleaner.
This is the guy who has worked on the Scala compiler. He says it will never be fast and there are things which are fundamentally broken (like above, and there are many more).
I think any start-up using Scala is making a big mistake.
That's standard IEEE 754 floating-point behavior. Almost all languages will do that (and languages that use bignums by default have their own problems). If you want more accurate floating-point (at a cost in performance) you can use Spire.
> This is the guy who has worked on the Scala compiler. He says it will never be fast and there are things which are fundamentally broken (like above, and there are many more).
He also says it's the best language available at the moment. And he's right.
A Long is 64 bits. An Int is 32 bits. A Float is 32 bits (8 bits exponent, 23 fraction, 1 sign). I don't see how anyone could expect a Float to have enough bits to represent the difference. The only different behaviour I can envisage is an error, but it is standard practice to disable these for performance reasons.
A Float on the other hand, by definition, is only an approximation. You can use fixed-point numbers, but they are either too slow or lack the required precision.
The main take-away imo is the line "every increase in expressiveness brings an increased burden on all who care to understand the message"
That line basically why I am not as fond of Scala as I originally was.
My defense of the inevitable "well hire smarter developers then!" is twofold (a) You're saying Scala is not a mass market audience language and (b) you aren't as smart as you at 4am, after you were just woken up because your code is broken in production.
I find the version without the .s much more readable as long as all the methods take one argument each. Haskell does it for everything, so this is certainly a viable syntax choice, though IMO it isn't nice when you have multi-argument methods.
More of these "This language sucks" blog posts need to focus on the problem domains actually being solved and less on the aesthetics of the tools. My team uses Scala as one of our primary backend languages and have been extremely productive with it. We're building large distributed systems that store and manage large quantities of sensor data and push Scala pretty hard. Are there warts? Yes, just as with any other tool. But the important part is that we create value quickly for our customers, and Scala has fit our problem domain quite well.
I've also seen too many consultants who get caught up in technology for its own sake, because that's what many of them sell (We use this new development methodology, with this hot new framework, hire us!).
Let's all spend less time worrying about what tools we're using and more time worrying about whether we're solving the right problems.
The Co-Founder of Typesafe, Paul Phillips, hates Scala too. Working on the compiler seems to have driven him mad (he says this, not me, but I don't disagree based on this performance.)
This is proper constructive criticism. The presentation is terrible, but everything he says is right. Including the part where Scala is still the best tool available today, even though it could be so much better than it is.
He says you need to be a "rocket scientist" to change the compiler.
We have computers that are thousands of times faster than the 1980's but Turbo Pascal, then, could compile tens of thousands of lines per second on that hardware. Scala is so complicated it takes minutes to compile large code bases.
Anyone remember what the claims were for Turbo Pascal?
They need to take a lesson from the OCaml or Haxe devs. Both have blazing fast compilers that create efficient code for every platform known to man... And both are very feature-rich languages.
He may be a bit interesting, but based on your assumption that he "hates" Scala seems to indicate that he is a very angry person (given that he still prefers Scala to other alternatives). I think he is emotionally invested in Scala and upset that it didn't turn out exactly how he would have like to see it, but "hate" seems like a strong (possibly incorrect) word to use.
Him switching from being neck-deep in compiler issues to actually using the language in anger on whatever it is he's doing now might end up being really good for the language. His twitter stream has started filling up with wtf's and really good bug reports.
Much of what he desires out of his ideal programming environment sounds eerily like CL or SmallTalk (though possibly closer to CL).
The textual representation of CL code IS the AST. You can change it to be whatever you want. You can programmatically manipulate the code objects represented by that tree using the same forms and idioms you use on plain old data. There's very little magic that happens "under the hood."
I can't even imagine how awesome the CL ecosystem could be with someone like Paul on its side. sigh
I've been putting in some time to learn Scala but he elucidates much of what bugs me about the language in this talk. I'm hoping to see a, "Good Parts" book but I'm not sure if that's a good sign.
It's sad that this particular blog post is getting double the attention because it's not a strong critique of Scala, which, like any good technology, is imminently critique-able. The extant HN thread got much more interesting Scala critiques than the blog post:
That said, I would add the following meta-commentary, which has nothing to do with Scala in particular:
Don't be scared away from Scala by the negativity. In fact, use said commentary as evidence that Scala has hit a maturity point that makes it worth exploring. When Rails first could come out, it could do no wrong, and I would get regular queries from less experienced techies as to why we weren't rewriting our code to use Rails, as though the hype made it a given that any web application should be in Rails from now on. Now that Rails is more mature, it gets regular negative articles. Using negativity around a mature technology has some underlying theme that is valid (performance for Rails, overly complex libraries for Scala), but not something that would or should scare someone away if they are eyes-open assessing the needs of their final product against the capabilities of the technology.
Really, we are in the infancy of software development. All languages are incredibly oblique to their runtime environments, especially in distributed scenarios. Any language that gets little but praise is simply not sufficiently understood by enough people to be critiqued, or for said critiques to get up-voted on news sites.
I am not, by the way, arguing that all languages are therefore equal in quality. What I am arguing against is this: often when there's a vote-up negative article about technology X, there's people who respond, "Aww shucks, I was about to use X for my next project, what should I use instead?" And the responses are, "Well, use Y instead", where Y is currently on the zenith of its hype machine. This is a bad strategy for assessing technology, because it's simply inevitable that Y will eventually receive a hailstorm of similarly valid critiques. Consider it a given that any technology in use today will look stodgy in forty years.
Instead, use the existence of critiques as a marker that a language is fairly well known and mature. It's rather like the appropriate way to use Yelp reviews: assume most of them are fake, assume nothing but positivity or negativity is wrong, and instead look for volume and breadth of tone.
I have written Scala on several large projects( and Play framework)
One of the problems with Scala is that there are a thousand ways to do everything, which is often insanely confusing to a lot of people. And another I think is that people try to teach scala like they teach other OO languages and it just doesn't work.
Scala is not that hard once you boil it down the set of features that your team wants to use.
After learning Scala and then teaching it to several java developers, I believe I could get someone productive in Scala in 5-10 hours.
There are a couple of cognitive hurdles, and a few difficult to implement features in the super deep realm of coding, but it's really not that hard.
I don't think I could do it with a book. I think I could do it with a combination of lecture, exercises, and a little Q&A. At least that has worked in the past.
I agree that it's hard to trim down the feature set you want a team to use, but for individual development it is really nice. I like building a solution to my problem and whittling it down to clear and concise code. The resulting can be information dense if you let it, but I like it.
I find myself spending lots of time reading Akka and Spray docs just to output a few characters. I can understand why highly volatile software can be tough in Scala. But I appreciate the concept of expending a lot of thought on a minimal amount code that is easy to read.
I love me some matchers with cases and gaurds. You can make some normally gnarly looking and hard to read decision trees into really concise easy to read cases.
>Scala is not that hard once you boil it down the set of features that your team wants to use.
Isn't that, essentially, what you already have to do with C++ to keep that manageable? If so, why not go straight for C++ and get improved performance in return?
C++ is not a functional language and it doesn't run on the jvm. So this is more of a question of what are you looking in a programming langauge. For teams that are already heavily invested in the JVM it's very attractive. There are also a ton of advantages in the multi-processing aspects of scala.
I'm learning Scala (coursera, twitter) to write game servers that can handle lots of request simultaneously. What's another good language for this? So far, Scala seems rather powerful.
For high performance/throughput, the JVM beats both Go and Node.js. As an anecdote, I implemented a web service that was handling about 6000 requests per second of real traffic, per EC2 c1.medium server instance. In terms of dealing with concurrency, I/O, reactive stuff and everything else related, you've got:
I love Scala as a language and would encourage you to learn it on the way to becoming a more rounded programmer. It does have its warts, and compile times kill me. On HN the two common recommendations are:
* Go
* Node.JS (with Promises while we wait for generators!)
I personally use node for large-scale stuff since more people know JS, but a lot of this comes down to personal preference.
Its interesting that you use Go (CSP) and Node.js (callback) and like them both. Generally CSP people belive that the Node.js approach leads straight to hell.
Rich Hickey is really good about why Callbacks are terrible (and that's why he implemented CSP in clojure):
"Like" is relative and based on tradeoffs. Loved Rick's talk, thanks.
This last year I worked on a project with people from the valley, we used Go, and everyone contributed quality code. This is because people in SF area know Go.
A year ago I worked on a project with people from the midwest, we used node, and got the same quality. Much fewer people in the midwest know Go.
Independent of my feelings about both environments, CSP, callback hell, etc, at the end of the day my team and I have to build a product, and I try to pick the tool that best matches our combined skillsets.
Node only runs on one core, you can start it more then once. This only works if the request well don't have to coordinate over the hole address space. You need to care all the shared state in a database, witch you don't really want to do.
Go, is pretty good for that and it helps to think about it. You can start on thread of control per request, like with Scala where you might start one actor per request but the difference is that you have first class channels to communicate. Witch is pretty powerful.
Most languages can do this. Some of them come with models for doing it (like Scala, Go, or Erlang) and others are best used with an existing eventing library like libevent or libuv (like Node).
I was at a job where I programmed in Scala for about 6 months. This was almost 3 years ago: immature tools (awful IDE support), slow compilers, long build times (this was partially due to Maven project with literally 50+ modules and too many unit tests), and inexperienced developers. Scala is too complicated a language.
I'm sure it's a little better now... but, it's not for me.
With Scala you feel smart having just got something to work in a beautiful way but when you look around the room to tell your clojure colleague how clever you are, you notice he left 3 hours ago and there is a post-it saying use a Map
So he was making reference to Clojure here. That's fine, but you don't have to make things complicated in Scala if you don't want to.
I love the semantics of Clojure, but until you get some optional typing and possibly another syntax baked in forget about it for a whole class of devs.
And if you would feel the urge to respond with something like "why is such important functionality in a library", I'll point out enforcing pre and post conditions (on a function) has a nice syntax that is part of the language:
Having made the choice between Clojure and Scala many times, always in favor of Scala, here are the 3 main reasons I keep going back to Scala (even though I don't particularly like it):
1. I like type systems. I want strong typing, I'd prefer stronger typing in Scala (ie purity constraints as type information etc). I don't want optional typing (if I need dynamic interop, I can make a case for opt-out typing, but I've never needed).
2. Performance. I spend a lot of time dealing with performance issues, specifically latency & throughput. I often have to back off of idiomatic Scala to achieve these goals (especially when it comes to GC pressure). Scala makes that easy & painless. Clojure doesn't.
3. Style (purely subjective). I don't like LISP style languages. My very first experience in programming is in Scheme, so it's not that, I just don't like how they look. It's fine for other folks to like them, different strokes and all that, but I don't like it.
There are a ton of things I don't like about Scala, but for me and my projects, right now, if I'm targeting the JVM it is the best choice and Clojure isn't even second.
I believe with schema you can get much of the same benefit and even more on top of that.
I think schema will still evolve and work together with core.typed (witch will also evolve) will be a awesome combo.
I generally prefer not having to right the types but putting down some automatically enforced documentation is nice once in a while.
> 2. Performance. I spend a lot of time dealing with performance issues, specifically latency & throughput.
I cant really say on this issue. But I know that the story here really changed and keeps changing. Because of macros we get library's that are where fast but feel easy and simple to use.
Some teams like prismatic, runa and relevance did some pretty performant APIs and used Clojure.
This non-obviously creates an extra object in the Some case. As opposed to:
if(opt.isDefined) opt.toString else ""
which creates 0. Not a huge deal in this specific case (unless this is a hot call). But this sort of thing is endemic to all of the standard libraries.
Edit -- only 1 extra object, but it is in both the Some & None case (which is sort of the point, it is hard to know with idiomatic Scala)
This is why I'm really happy with the Clojure community. People in Clojure get that types are useful and important. You don't have the "I don't understand that, so I'm going to call it unimportant" attitude. Instead, you have people using Clojure as a lens to explore and, one hopes, solve the problem-- even when it seems so difficult as to be almost infeasible (such as static typing on a Lisp).
Clojure is a dynamically typed, JVM language-- now. (However, ClojureScript is also pretty far along.) It might not always be that way. It will evolve according to the needs of computer science over the next 20+ years.
>With Scala you feel smart having just got something to work in a beautiful way but when you look around the room to tell your clojure colleague how clever you are, you notice he left 3 hours ago and there is a post-it saying use a Map
I don't get this. Scala has a great collections library, including a Map type. What, exactly, is the author complaining about?
His point is that Scala and the Scala community dont just use maps, they always want everything in types and that is why every library does it that way. Its bad practice just to use a map. In Clojure land its the other way around even if we put something in a type (deftype) we right interface to make it look like its not (defrecord).
Its not what is possible, but what is. And the fact is that all the Clojure web framework and library's use the same data structure even if the underlying implementation is different. See how ring uses much of the same thing as the pedestal service.
This is actually a good example of something I don't like in Scala. They don't make this sort of differentiation easy enough. Adding a Haskell style newtype would be really, really useful.
AnyVal's would probably be sufficient except for the following:
- Instantiation of the MyNewType happens all the time and is not obvious from inspection of the code (generics, use as another type if we implement a trait, etc).
- If we want to call any of the methods on the wrapped type we have to call directly to the wrapped type violating Demeter.
- Verbosity.
It seems you've done a lot more with them than I have. I'm looking forward to crashing the compiler -- the true badge of honour amongst Scala developers ;-)
They still have uses for disambiguating implicits. There are at least four monoids for the Int: 0/+, 1/*, MinValue/Max, and MaxValue/Min. It is useful to tag them so one can specify which monoid one wants.
Not needed in my mind. I would rather have less devs then C syntax. Not trying to be elitist but clojure will never not be a lisp, and if somebody can move from a(b) to (a b) then let him do python.
I also work in the same company as the poster. We are
currently running a huge Scala/Play project where the
team is a mix of many young developers (< 5 yrs) and a
few seniors. Overall it is a very pleasant experience.
There are multiple other projects using Scala which share
this positive feeling.
It is difficult to explain these reactions, but they are
common among my colleagues. These are senior programmers
who are generally very good with any programming
language/task. They will pickup something new and be
productive in just a few days. They usually end up liking
Ruby, Javascript, Clojure and for good reasons.
Scala on the other hand requires a lot of attention and
work to get mastery. One can get started in days but to
exploit the real power and appreciate design choices
takes months if not years. In my opinion this is an
important factor why these smart developers react so
badly to Scala which for them is just another tool which
takes too much time to grasp.
There is little Scala can do. Maybe it should become less
ambitious. No macros, no compiler plugins, do not
challenge FP etc. But then it will not be the Scala we
all loved :) Also, it is important to note the blog post
does not criticise Scala in isolation. It used Spray DSL
for routes and Gradle as a build tool, maybe that
particular combination increases the pain.
http://overwatering.org/blog/2013/12/scala-1-star-would-not-...
Some thoughts: I've worked on several large scala projects, and I've found that long incremental compile times are often a sign of bad encapsulation. If you change the type signature of a public method then any file using that class needs to be recompiled.
I've found that explicit type annotations on method return types help a lot here:
This has type `BanditRef => ConcreteSimpleBandit`. If I change the implementation and return a ConcreteNonSimpleBandit, the inferred type signature changes to `BanditRef => ConcreteNonSimpleBandit`. If I use an if-statement and return one or the other, the return type will be the nearest superclass of both (say a ConcreteBandit).However, if I explicitly annotate it to return a BanditLike
then only the class in question needs to be recompiled.The author is spot on about the use of infix methods. These are nearly always evil. What would be great if Scala gave you a way to explicitly declare certain functions as infix, and everything else uses the java-style calling convention. For a monoid, a |+| b |+| c makes perfect sense. However, consider:
Yeah, you need to do work to figure out what's going on. Compare to: But I suppose the former will save some bits ('.' and '(' take more bytes than ' ', right?).