Scala – 1 Star Would Not Program Again
overwatering.org
overwatering.org
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:
def getBandit(ref: BanditRef)= {
...
ConcreteSimpleBandit(...)
}
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
def getBandit(ref: BanditRef): BanditLike = {
...
ConcreteSimpleBandit(...)
}
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:
optionalResult map (x => x*x) filter (_ % 2 == 1) getOrElse -1
Yeah, you need to do work to figure out what's going on. Compare to: optionalResult.map(x => x*x).filter(_ % 2 == 1).getOrElse(-1)
But I suppose the former will save some bits ('.' and '(' take more bytes than ' ', right?).My short handed criticism about Scala is this: It's the C++ of the JVM.
Specifically it has many features of C++ we thought we left behind: - slow compile times - complex language features and syntax
The language features have a benefit, and a cost. I just personally believe the cost outweighs the benefits for me.
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.
See other comments below where co-founder of Typesafe (who has quit) gave a talk explaining why Scala is doing everything wrong.
In his video he has a slide with the words "No wonder nothing works" and on the slide:
scala> val x1: Float = Long.MaxValue
x1: Float = 9.223372E18
scala> val x2: Float = Long.MaxValue - Int.MaxValue
x2: Float = 9.223372E18
scala> println(x1 == x2)
true
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.
> val x: BigDecimal = Long.MaxValue
Problem solved. Or is it?
If that's what you've understood from that talk, then you haven't heard basically anything he said.
> val x1: Float = Long.MaxValue
OK, I'll byte, name your (safe for startups) programming language that presumably doesn't do that.
> 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.
"Scala is to Java what C++ is to C".
http://parleys.com/play/528cbfc3e4b084eb60ac78f2/about
With slides: http://www.slideshare.net/extempore/keynote-pnw-scala-2013
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'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.
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?
According to Embarcadero Turbo Pascal memorial page, Turbo Pascal 5.5 was compiling 34,000 lines/minute!
http://edn.embarcadero.com/article/20803
Having been introduced to Turbo Pascal line of compilers, spoiled my expectations in regard to C and C++ when I got to learn them afterwards. :)
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.
https://news.ycombinator.com/item?id=6829725
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.
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.
Write an book on leanpub. You'll make a fortune...
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.
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?
* 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.
Node seems promising (it's not techncially multi-threaded though?)
I wrote a little command-line RPS game playable over a local network in node: https://github.com/quantumpotato/node-rps
Didn't realize Go was good for many-connections, will have to check that out. TY
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.
One the JVM you can do this CSP style where well with Clojure (https://github.com/clojure/core.async).
Interesting video why CSP is best:
Rich Hickey is really good about why Callbacks are terrible (and that's why he implemented CSP in clojure):
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.
- Actors (local or remote): http://akka.io/
- STM: http://nbronson.github.io/scala-stm/
- Futures/Promises in the standard library: http://docs.scala-lang.org/overviews/core/futures.html
- Async (e.g. C#'s async): https://github.com/scala/async
- RxJava Observables: https://github.com/Netflix/RxJava
- Iteratees: http://www.playframework.com/documentation/2.2.1/Iteratees
- Scalaz Streams: https://github.com/scalaz/scalaz-stream
And the list can go on.
http://de.slideshare.net/wooga/erlang-the-big-switch-in-soci...
I'm sure it's a little better now... but, it's not for me.
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.
"until you get some optional typing"
There is work being done on an optional type system:
https://github.com/clojure/core.typed
There are also some interesting experiments in enforcing specific data structures:
https://github.com/prismatic/schema
Much effort has been made to make contract programming easy in Clojure:
https://github.com/clojure/core.contracts
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:
http://blog.fogus.me/2009/12/21/clojures-pre-and-post/
I find that every time I read an article about Scala I am left wondering "Why don't these people just use Clojure?"
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.
That is quite fun. Lisp had experiments with static types for a long long time. Look at things like Qi and there history.
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.
Can you give an example of when you had to do this? I often wonder about the performance costs of chaining together several collection API calls.
def foo(opt: Option[Bar]) = opt.map(_.toString).getOrElse("")
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)
The schema library form the prismatic guys should be what you want, its pretty powerful.
https://github.com/prismatic/schema
Aria Haghighi - Prismatic's Schema for Server and Client-Side Data Shape Declaration and Validation (http://www.youtube.com/watch?v=o_jtwIs2Ot8&list=PLZdCLR02grL...)
For static type checking: https://github.com/clojure/core.typed
> possibly another syntax baked in
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 don't get this. Scala has a great collections library, including a Map type. What, exactly, is the author complaining about?
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.
val cookies = Map("sessionid" -> "1234567")
val headers = Map("Content-Type" -> "application/javascript")
setCookies(headers) {
setHeaders(headers) {
complete { obj }
}
}
With Scala's "make everything a different type" approach, that's a compile error - setCookies will expect a List[Cookie], not a List[HttpHeader].Those of us living in Scalaland are not as smart as the Clojure guys. We make mistakes sometimes and find it handy when the compiler yells at us.
case class MyNewType(x: String) extends AnyVal
What do you want to do that that isn't sufficient for?You can also use tagged types:
http://eed3si9n.com/learning-scalaz/Tagged+type.html
But most of the methods will untag the type. I.e., ("foo" @@ ValidJsonString).substring(3,7) will be a String, not a String @@ ValidJsonString.
http://etorreborre.blogspot.co.uk/2011/11/practical-uses-for...
Scalaz implements this, so you can use it straight away. We use it mostly to control implicit selection.
1st they don't propagate, call a function on the tagged type and it returns the underlying type.
2nd they aren't type safe against the tagged type, so you can pass tagged types into functions that take the underlying type by default.
3rd in practice my code with tagged types ends up having lots of boilerplate and/or magic code that is hard to understand.
4th there are some pretty heinous compiler bugs that you will encounter with tagged types.
val x = 1.0 @@ Kilograms
val y = x*x
y is not a Double @@ Kilograms.http://docs.scala-lang.org/overviews/core/value-classes.html
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.
https://groups.google.com/d/msg/scala-internals/153H3Ya4Nxk/...Taking my downvotes and moving on, I am.