M'eh. Yes, Scala has flaws but I feel like this talk makes too much of minor annoyances. Ultimately you make an engineering decision about platform. Do you want decent performance, lotsa libraries, and a modern statically typed language? Scala is arguably your best option at present (yes this can be argued with; no that isn't an interesting argument to have). Maybe we'll all be using Rust/Haskell/whatever in 5 years, but in the meantime I got code to write and products to build and I'm using Scala for better or worse.
Specifically:
- Code on slide 3 has typos. (Yeah, that's minor)
- Lambdas are slower than Java 8 -- that's because Scala currently supports Java 6+. Java 8 has been released for 6 months. This is a ridiculous complaint.
- Heavy in terms of concepts -- another ridiculous complaint. If you want to keep on writing Java, keep writing Java. If Scala didn't bring new stuff to the table it wouldn't be interesting.
- Implicits -- agreed they can be misused. Type classes are the way forward.
- I don't understand many of the "very ugly" complaints. Yes, collections have lots of methods. Is this surprising? Yes, library code may be written in an abstract way. So what? Yes, DSLs look like DSLs. Yes, abstracting over arity is a problem in all statically typed languages. etc.
There are valid complaints to be made about Scala. I feel this talk demonstrates a lack of understanding of the language, and many of its complaints are in fact misunderstandings.
To me the biggest issue this talk reveals is that if you come from an OO background (which I assume the author does) then learning Scala will require a change of mindset. I don't think it is fair to make this a language complaint though. Scala makes it fairly obvious what you're getting yourself into and, as I said above, if you wanted to keep on writing code the way you have in the past it's not clear why you are using Scala in the first place.
Scala gives you an excellent way to go about changing your mindset though. I feel like functional logic at a granular level wrapped in OO structures is a very logical way to go about building the kinds of software that Scala is being used for.
> If you want to keep on writing Java, keep writing Java.
Ah! But that’s the point, because Scala is pulling a bait-and-switch. If it were only a modern statically typed language I wouldn’t complain so much about it (and I really do complain a lot about Scala, I guess). Yes, I find its gaudy indiscrimination aesthetically unpleasing[1], but that’s a matter of personal taste. The problem is that Scala still markets itself as “a better Java”, and people are drawn to it so they wouldn't have to write getters and constructors. And at first, Scala does seem to be that. Only after a while you realize that it’s a whole other beast altogether — not necessarily the one you bought into. If Scala were marketed as “a JVM language Haskellers can learn to live with”, I’d have no issue with it (except the aesthetics, that is :)).
[1]: Yet, with its near-infinite list of features it can't even type immutability, which even Java 8 can through its pluggable type systems.
Indeed, if Scala wasn't closely compatible with Java (in terms of both syntax and interop) it would not have so much traction. That's the deal with the devil that Scala made, and one reason it has an excess of cruft. For example, no language needs both traits and abstract classes, unless that language wants to interoperate easily with Java.
I am broadly agreed with you. Scala could do with trimming, and I'm optimistic that both Typelevel and Typesafe will accomplish this in the near future.
> For example, no language needs both traits and abstract classes
So abstract classes are the unnecessary bits in Scala? :)
Choosing to do it all at once shouldn't surprise you as it's kind of Scala's modus operandi. I would say no single language needs algebraic types and inheritance and structural types and dynamics (and implicits and macros).
The deal with the devil Scala made, IMO, is when it tried to be both a research language and an industry language at the same time (Java interoperability is but a small part of this deal) without realizing that what's good for research (many different ways of doing things) is often bad for industry.
It's the Las Vegas of languages: gaudy and confusing, but if you look at just a tiny part of it and squint, for a second you can convince yourself you're in Paris.
If you buy into object-functional, combining ADTs and inheritance as Scala does is quite reasonable.
It will be interesting to see what Scala is like in a couple of years. I think (hope) many of the issues will be resolved. Just going over the list you give:
- Implicits are useful. Implicit conversions, the evil part of implicits, are mostly going away via deprecation and other mechanisms.
- Structural types might go away if higher kinds are curried, or there is syntax for partially applying a higher kind.
- Dynamics. Who uses this? Why was it even added? I'd nuke it in a second but I don't know of any plans to remove it.
- Macros aren't even officially in the language yet, so it's a bit early to call for their removal :)
Ultimately is comes down to implementations. The idea of statically typed FP inspired languages has been around forever, but the implementations just haven't been up to scratch. Where are the alternatives to Scala (that is, statically typed, run on the JVM)? Things like Kotlin etc. are still in development and don't really offer much over Java. It might be in 5 years that Rust has a sufficient ecosystem to make it a viable alternative to the JVM. I think a lot of big data systems (in the area of Cassandra / Kafka / Hadoop) projects would happily move over to Rust, just to avoid GC issues. Haskell is the other alternative with traction, but it's an even further leap for most developers so I'm not convinced.
I prefer a much more pragmatic approach. From where I stand, statically-typed FP languages like Haskell are very interesting but are still in the research stage. We don't even know that that's a direction worth adopting in mainstream languages. Some ideas (pattern matching) are easy to understand, but others? Personally, I think static types going beyond those offered by Java could be very beneficial, but I'm not convinced that the type systems used by Haskell or Scala are the way to go.
We do know that FP does allow for more general abstractions, but those usually come at a cost. They are harder for people to understand, and frankly, haven't been proven to increase code quality and maintainability. Yes, they're elegant like mathematical equations, but equations don't need to be changed and maintained by large teams of people over many years. A language like Haskell gives you more tools to think of your program ahead of time at the expense of thinking about it when it runs (with a debugger, profiler etc.), and I'm not sure that's the tradeoff the industry should make. Math is a great tool, but I'd learn how to catch a ball a lot faster by trial and error, then by learning how to rigorously compute its trajectory.
I think people in the industry should wait for more evidence of the utility of the more advanced FP concepts before rushing to adopt them. Of course, that doesn't mean people should be working on novel approaches and trying them. But my problem with Scala is that it is really a research language that tries different unproven approaches (and that answers pretty much all your questions about why certain features were ever included -- that and the non discriminating taste of its designers). But it's dangerous because it tricks people into thinking it's something else.
The worst thing about Scala seems to be that the community always have to deal with a single nutjob on Jihad, first Harrop, then Colebourne, then Beust, now that guy.
I believe Clojure is less directly interoperable. For instance, a Scala class is a Java class. I believe creating a Java class in Clojure is something you have to call into a library to do.
Update: reading the Clojure docs, the main issue I see is compiling Java code against Clojure code. Clojure has a number of constructs for calling Java code and creating Java objects, but it's not clear to me how you define an API in Clojure that Java code can then call.
Actually, Clojure interoperates with Java much more cleanly, and easily than Scala. Every Clojure collection is a Java collection and vice versa. Every Clojure map is a Java map and vice-versa. Plus, because Clojure is less statically typed than Java, Java typing idioms don't clash with Clojure's.
> Plus, because Clojure is less statically typed than Java, Java typing idioms don't clash with Clojure's
Well, you made me laugh. :)
But the real deal is compiling stuff to JVM bytecode ahead of time, which Java code can then be compiled against. It's not clear to me that Clojure provides this, which is what I was getting at.
There is a point in my presentation that says that some of these annoyances are easy to overcome in a real project. But some of them aren't.
As for the misunderstandings - the "bad" parts are ..bad. The ugly parts may not be bad, but are ugly (which is subjective, and I think it's implied it's subjective)
Perhaps the issue is that the slides don't really stand on their own. Without hearing what you have to say for many of the slides it is difficult to really get the point you're making. Let me just address the "bad" slides, and what I got from them.
Slide 8
- Compiler too slow. A common complaint. Agreed it could be faster.
- Ecosystem. Don't really get the point here. Yes, Scala has different idioms to Java, so naturally Java libraries don't make for idiomatic Scala code. There are many mature Scala libraries. Binary incompatibility has not been a problem for me in at least two years, and it is a necessary artifact of Scala compiling a language that is not Java to JVM bytecode.
- Lambdas I addressed above.
Slide 9
Don't know what point you're making here.
Slide 10
Mostly addressed above. Syntax doesn't bother me. There are regular rules and the alternatives are a consequence of those regular rules. Would consider removing eta-expansion. Never had an issue with any of the rules though.
Slide 11
See above.
Slide 12
See above on type classes.
Slide 13
This is very generic. Applies to all languages.
Slide 14-15
Don't really get it. You can write code in many different ways. Applies to all languages.
Slide 16
This is very generic. Applies to all languages.
Slide 17
Don't get the point you're trying to make with this code.
Slide 18
This is presumably a slide that summarises this section. Without hearing what you have to say here I can't really interpret this.
"I don't understand many of the "very ugly" complaints. Yes, collections have lots of methods. Is this surprising?"
Perhaps "very ugly" refers to method names like "/:". (Example on slide 22. There are many more examples of "very ugly" in that slide, too.)
This reflects on the culture, not the language, but it means in practice you will need to read lots of code with random punctuation used for method and function names. Unless you never use any libraries and never work with other Scala developers who write code like this.
"... in practice you will need to read lots of code with random punctuation used for method and function names."
In my two or so years of Scala I've yet to see anyone actually use /: or similarly named methods, and if they did I would make sure it never gets past a code review. Yes, the methods are still there, but in my experience people avoid them (even Odersky thinks they were a bad idea), and libraries with a lot of symbolic methods (Scalaz, and everyone's favorite whipping boy, Dispatch) are not particularly mainstream.
So my experience at least has been the opposite of what you assert. I would instead say that "... in practice you will NOT need to read lots of code with random punctuation used for method and function names."
I feel that most of (not all) the criticisms are fair, but superficial.
True, the IDEs are poor, for a certain definition of poor. Had I not used IntelliJ for Java, for example, I'd find IntelliJ for Scala amazing. Knowing how much better it can be spoiled me, but frankly, IntelliJ for Scala is not bad. It just could be better.
Also, Emacs has a very robust Scala mode.
True, there's a lot to learn before you can consider yourself fully fluent. You do not need to know everything, however. And once you've started on the path, things tend to flow naturally. For example, implicit conversions are easy to grasp. Once you understand them, implicit parameters and type classes are not much more complicated. Once you know type classes, it opens the door to a lot of functional "design patterns" - functors, applicatives, monads... these are not strictly necessary, but they're fun to learn about. And they teach you algebraic data types, which in Scala means case classes, sealed traits, ... it all sort of flows naturally.
True, it's easy to write absolutely un-maintainable code. While that's true of any language, Scala makes it rather easier than most. It's also very easy to write highly maintainable, legible code, and to avoid complex, ascii art based operators (or at the very least to offer wordy equivalences at 0 cost through `@inline`). I feel that saying "it can be hard to read, if you don't follow basic guidelines" is a bad reason not to use a language. A good reason to be careful, though.
My personal experience is that, once you start feeling comfortable with the language, you get much more productive than with Java. It does require some initial work, though: if all you know is OO, learning how to design your code for composition rather than inheritance takes a while - it takes a while just to realise that it's not a bad idea, let alone embrace it!
Also, ScalaCheck. Man, do I wish there was a good Java equivalent for some of my legacy code (that would not require me to rewrite all of my tests).
Scala does take more work to learn than Java, but I never choose Java over Scala for a new project. Scala is just so much more modern and expressive.
You can write perfectly readable Scala. It just takes some taste and common sense, or alternatively follow guidelines such as: http://twitter.github.io/effectivescala/
We've found IntellJ + Scala to be an excellent combo for our purposes.
I've been using Sublime as my Scala "IDE" for a while now - what it loses in certain 'critical' IDE features like code completion and variable extraction it gains in speed, ease of use and lack of bloat.
I agree that as far as real IDEs go, IntelliJ is the best - but that's not saying much. The rest are pretty awful. They all do many things poorly, whereas Sublime does a few things very well.
I agree that the criticism is fair. It does seem to come from someone with relatively little experience, but if anything, that makes it more valuable. Languages need adoption and new adopters by definition have no experience.
Regarding IDE support, which inevitably comes up when discussing Scala, an honest question: what are good IDEs for Ruby, Python, Clojure, JavaScript, Haskell, OCaml? Is there a good IDE for C++ besides Windows-only Visual Studio? For C?
It seems that Scala always get compared to Java in that domain, but in my experience Java is the exception, not the norm.
(Edit: I assume support for CLR languages is great too?)
Ruby: RedMine/IntelliJ
Python: PyCharm/IntelliJ
Clojure: Cursive/IntelliJ
JavaScript: IntelliJ + all JetBrains IDEs
Haskell: Dunno
OCaml: Dunno
Is there a good IDE for C++ besides Windows-only Visual Studio?: CIDR undoubtedly will be, but it's still in beta right now.
For C: AppCode
If you compare IDE support with those languages, then Scala's IDEs are stellar. I would dare say that IntelliJ IDEA for Scala is better than Visual Studio.
And how long did it take Eclipse to get to that non-perfect-but-good state? Several years. When I checked 6 years ago, C++ support had been already there for a few years and was quite awful. And C++ type system is much less powerful than Scala's, so it should be theoretically much easier to provide good IDE support for.
The C++ template system is turing-complete and partial specializations are more or less equivalent to the way you do type-level programming in Scala with different priority implicits, so I don't see that it would be any easier to support than the Scala type system.
If turing-completeness were the only criterion to judge programming languages, then we'd be all programming in Brainfuck. Indeed, C++ template system is turing-complete, as well as Scala's. But saying they are more or less equivalent is a complete misunderstanding. The main purpose of type-systems is to prove/disprove correctness-related properties of programs. The better the type system, the less frequently it rejects a valid program or accepts an invalid one.
I could go on and list a number of features that Scala typesystem supports natively which C++ does not (e.g. type bounds, path dependent types, variance control, existentials, abstract types...), but there is no need to do that.
There is one much bigger difference between them: C++ templates are not a first-class citizen of the C++ type system. They are just a (turing complete, but quite limited) macro-language bolted on top. Actually the compiler does not perform any typechecking of generic code. All the typechecking happens after macro expansion when generics are gone, and the typechecker needs to understand only concrete types. This is completely different than in Scala/Haskell/F#/C#/Java/OCaml typesystems, which can reason about generic types and can fully type-check generic code.
All true and all quite irrelevant to the problem at hand. An IDE does not need to know which properties a type system makes it easy or otherwise to prove. It just needs to understand the type system. And a useful C++ IDE absolutely does have to understand the template system and the way it interacts with the type system - maybe a compiler can get away with running them as two separate stages, but an IDE needs to do things with incorrect code as well as correct code.
"And a useful C++ IDE absolutely does have to understand the template system"
I've never seen a C++ IDE that could fully type-check template-heavy library code before its actually used beyond just syntax checking and limited type-checking the non-generic types. This is something that can't be done just because of how C++ templates are specified ("duck-typing"), not due to an implementation detail in the compiler/IDE. This is also the reason why good error-messages from templates are so hard to make - type errors are detected at the concrete level (late), not at the generic level (early). This is going to change when C++ finally gets "concepts" and will be able to reason about generic types (but this would be still a very long way to something like Haskell or Scala has).
Once you know type classes, it opens the door to a lot of functional "design patterns" - functors, applicatives, monads... these are not strictly necessary, but they're fun to learn about.
For a certain value of "fun", I guess.
Generally I find in engineering that it's best not to add abstraction (or other forms of complexity) to a system unless there are strong, clear benefits to doing so. The more we learn about Scala, it's just not clear that it delivers those benefits (in proportion to the time investment it demands).
It's not that I don't "dig" abstraction. It's just that I have an infinite list of things to learn about (some fun, some not so fun) in any given development environment. (In general, most of these are in the non-fun category: dealing with dependencies,build tools, and legacy quirks that can never be fixed).
And another infinite list in my own problem domain -- you know, that thing I'm supposed to be, theoretically, directly working on (in the service of which all of these fancy software tools were supposed to be a means, not an end). Plenty of very real and juicy abstractions. More than I can ever hope to get to the bottom of, in fact.
But don't get me wrong. If applicatives and such are your bag, then that's great. Maybe Scala is the right language for you, then.
I agree with you in terms of abstraction; I do believe Scala adds a lot to practical programming as well. I feel the community is tainted by a bunch of type-nerds trying to compile their Haskell, and don't care about writing simple, maintainable code.
We use Scala because it is speedier to push features. I work much quicker in it, and we don't have to worry about a lot of the stuff we would in Java. That said, we don't use a bunch of the most complex features of the language (I am just talking simple pattern matching, map/flatmap/filter/unzip). So far, it's actually the most productive language we've used.
Our dig is the community and things peripheral from the core language: documentation is generally awful (Play, SBT). Dependencies management is awful (SBT doesn't work). Libraries are overly complex (Dispatch). And compile times suck.
I'm a pretty big Scala fan, but I think this post is spot on. A lot of the stuff that's fun is not terribly useful, and I see a lot of people in the Scala community going down that road. The most perfect codebase in the world doesn't mean much if it doesn't do anything.
This is why, despite feeling real weird about it, I'm writing my current personal project in Rails rather than Play. It's one case where worse-is-better kind of benefits me--it forces me to focus on my problem, rather than on all the cool bright-shiny-objects that are not my problem.
(There's also a discussion to be had about the Scala-should-be-Haskell crowd, who I think come from a good place but are led by some of the most overtly poisonous people I've ever had to deal with.)
As I said, they're not necessary and I don't think I've written useful code that explicitely used monads, for example - well, aside from for-comprehensions, but you could argue that it's not explicit.
But they are fun in that, once you start understanding what the fuss is all about, they open your brain to new ways of thinking, which is always good - instead of learning how to be really really good with a hammer, I like to know about screwdrivers as well, for the odd case where that nail is kind of screwy.
I do understand your point about an infinite amount of things to learn in a finite amount of time. What I personally do is focus my study of tedium (build tools, say) and domain-specific concepts for work-hours. These things are required for me to be good at my job, and it seems fair that I improve on them while doing that job.
The other, more theoretical (type theory, functional abstractions, fun data structures...) or less directly applicable (odd languages, new concepts such as reactive programming or actors...) subjects I study on my own time, when I have it, when and if I feel like it.
It means that, for example, it took me a solid year before I felt I had some degree of fluency in Scala, which was frustrating. On the plus side, I now have some degree of fluency in Scala.
Often the argument is that if languages are superheroes, Scala is trying to be one with all the possible superpowers. When you learn how to use them and have control over when to use them (and for good or bad), everything will be a breeze. But the assumption that everyone will spend time learning the right ways and not use in production before achieving zen is impractical.
If you compare Scala other recently released languages (swift, kotlin, ceylon) they're all kindof similar, some claim to be less complex but imho aren't. Functional + OO is becoming the norm: the C# team is considering to add pattern matching and it looks like java 10 may have some twisted form of type classes.
'Scala the language', is imho very nicely designed, the problems arise in the compiler implementation and the core libraries. Scala carries around too much dead weight in it's core libraries. Some poor choices were made while scala wasn't widely used yet and it's very hard to fix that now. If you look at the roadmap for scala it's obvious that they are trying to address these issues.
Clojure is much, much less complex then Scala and it is functional and OO. Many people see clojure as purly functional but clojure programmes are often designed in OO style as well.
OO here meaning polymorphism over types of your data 'object'. The diffrence is that you usally never mutate your object.
It is fair to say however that the emphasis of clojure is functional and your code is expected to be functional style, only when you really need it, you start adding polymorpism but even then protocolls are expected to be a implementation detail quite often. Also, we access our objects the same way we do our hashmaps and even the same function often work on both objects or hashmaps.
Some people might of course dislike this approche where OO is not really not used in the traditional way and is kind of pushed down. So clojure I would say, is techniclly multi-paradigm but culturally its not.
We've had dynamic OO+FP languages for a very long time but only in the last 10 years have we seen them with static type systems. I really like clojure (though I haven't used it in anger) but I think you're wrong when it comes to complexity.
Complexity with dynamic languages grows with the size of the project. I know that because of the focus on purity & immutable data structures clojure mananges to mitigate this problem but I'm afraid it's still there.
The last few years several features have been added to clojure that increased the complexity(/surface area) of the language and the documentation is often a mess. I'm not a clojure hater, just pointing out that the complexity with clojure lies elsewhere.
edit: kinda forgot about Ocaml (~18 yrs old apparently)
> Complexity with dynamic languages grows with the size of the project.
I was talking about language complexity, not how complex the project is.
That said, I have nothing against static typing, my argument was not really about typing at all. It was more about how OO and functional interact in clojure compared to java. Also types by itself dont really make all that good of a documentation, at least not the kind you care about when looking something up in the internet.
I am a fan of schema, and I think the future really is in the combination of schema and core.typed. I dont really like to devlop with pre set types and structures, but you could with schema/core.typed. I prefer to work dynamiclly and once im happy with the shape of my data, I 'set it in stone' by writing the correct schema for it. Then you can just always validate everything during devlopment/staticlly. When you deploy you can turn on validation only for data from the outside. This is how I would like to do it, until schema and core.typed work together I just use schema.
For the most part macros make most code much, much easier to read. The clojure compunity is also really fixed in its way, how and when macros are written.
Take one example, core.match. Now in a language that does not have pattern matching code that can be easly written with pattern matching is very hard to read. In clojure its very easy to read.
Now one might argue that a 'good' langauge should have support for pattern matching. To that I say, the language creators can never have all the features everybody wants, it will slow down devlopment of the language and increase complexity.
I would rather read one or two nice clojure macros that reduce tons of boilerplate as you would need in other languages. The same happens in other languages, for exmaple rust. I really enjoy using macros there as well. Give me a language with macros 100%, it improves read and write ability in the waste majority of cases.
If you really belive that core.typed makes clojure as verbose as Java then you have not looked at it. Also, its not like people use clojure over java because they dont have to write down types. There are tons of other reasons people use clojure.
Also, core.typed can do things that java can not.
> Yes, but it doesn't even have types!
While I understand what you mean, you should write down what you mean. Clojure has types, but not static typing.
... except Scala isn't confident enough to be an instrument. It has to be all of them it once. It's a trumpet with strings taught across the bell (which you can play with or without a bow), and drum skin draped over the leadpipe.
It's a construction set with many pieces which you can combine to make new instruments. Maybe you have a mouldable body which can be made to support one neck and several auxiliary strings... and then you have a harp guitar. Maybe add some tenor strings to that later.
"support one neck and several auxiliary strings..."
And then as you add more and more features suddenly a case class has 22 and the whole thing crashes down but nobody told you about the 22 airity limit because "the ivory tower says thats bad design and I don't care what the real world needs" and although redesign is simple enough, its kinda shocking. I wonder what other silent spinning propellers can be walked into without warning. Maybe none, maybe lots, but I don't look forward to the ensuing ivory tower tongue lashing because I dared to use it in the real world.
Languages shouldn't get in your way. Even if the real world IS doing it wrong, it should at least support you failing with some style and grace.
And as the powerpoint shows, that compiler is possibly the slowest compiler I've ever used for a given complexity of task. Really... my project was an internal use only super specialized vaguely crud app using play framework for weird engineering data, but nothing fundamentally shocking or unusual, and a full compile from clean source shouldn't take 7 minutes and 33 seconds. What is that like one second per line of source?
Those complaints said, everything worked and it was vaguely enjoyable and interesting although a boring CRUD app does not exactly scratch deeply into the language features. Was a fun experiment, probably wouldn't do it again.
You know quite well that the removal of this restriction is brand new and it would be very easy to encounter it in the wild.
Why do you go out of your way to use smarmy tactics to argue against anytime someone who has a legitimate complaint? It would be way more productive to acknowledge the weaknesses and then tell the good story of Scala.
There are valid complaints about Scala, but the complaints from all those HN armchair experts are far removed from it. There is nothing useful to be done except making fun of it.
Are you claiming that there wasn't an arity limit on case classes that you could run into through no fault of your own using the Scala web stack? Or just that if you had to diagnose that problem it shouldn't bother you as it isn't a valid complaint?
What would elevate someone from HN "armchair expert" in your mind, such that their complaints were valid? Is it even possible for someone to mention something they don't like about Scala without you immediately dismissing them as not knowing what they are talking about?
The IDE story has vastly improved in Scala, certainly nowhere near that of Java but decent nonetheless. The best way to shoot yourself in the foot is to have automatic build turned on in your IDE and to run SBT in a separate terminal; with that approach you get dog slow compilations, blocked UI, and other hair pulling madness. When SBT is boss (i.e. IDE auto build turned off and compile target shared between the two) then you'll have a far saner development experience.
The OP hasn't been using Scala for long so many of his gripes boil down to lack of experience. You have to learn the ropes, the (myriad) corner cases, etc. of the language before things start to click.
It's like starting out in Haskell, where on earth do you even begin to understand this utterly new paradigm, much less go into production with large scala projects in it? The answer is: you don't, you learn, learn, learn until you're well grounded in the language and its frameworks; then you bet the bank on it because you're sold on its clear-as-day powers.
I'll go out on a limb and say that the only viable type safe alternatives to Scala and its ecosystem are C#/F# on .NET, and Haskell. In other words, yes, Scala has its warts, but overall is pretty much unmatched in terms of expressivity, power, and performance.
I like Scala, but it gets me that the official IDE, Scala IDE, is so utterly broken. If you let the IDE handle the build, you'll constantly get spurious compilation errors, which in a statically typed language are unacceptable.
Letting SBT do the build may work, but come on. This is the official IDE! Is there any acknowledgement in scala-ide.org that you should let SBT to do the build? Do Odersky and the guys at Typesafe use that setup, or do they suffer their IDE silently?
Couple things to keep in mind: Java IDEs have had millions of man hours put into them; there's a reason they're rock solid reliable; that and Scala's power is a double edged sword: tooling becomes a more difficult proposition with greater language complexity.
As Scala users we're basically guinea pigs in the IDE department. Having suffered from the relative stone ages of 2010 era Scala tooling I can honestly say that if you're considering picking up the language, you've come at a great time ;-)
re: sbt running the show, not sure about IntelliJ but the core Scala IDE devs will drop that bit of knowledge when a user moans on the mailing lists about blocked UI, spurious syntax errors, and other bundles of joy.
Builds are always scripted with explicit settings, which anyone can run, with the same results, regardless of what editor and preference settings they use. (so long as needed compilers are installed on server/workstation)
I think we're not using the word "build" in the same sense. I meant when writing code with your IDE, not when building the deployable artifact. In Eclipse this would be in Project -> Build Automatically; I forget the setting in IntelliJ.
Incremental compilation in the IDE is useful because you see errors as you type. This is an entirely separate issue from reproducible builds, etc.
OK, so you are talking about the ability of the IDE to scan (and parse where needed) the code and libraries to generate a symbol table for validation, auto-completion and definition / usage look-up.
Yes, but note that for this the IDE needs compilation, which is why I used the word "build" (perhaps confusingly).
Eclipse for Java does this perfectly, and I assume many other IDEs do so too. Scala IDE, which is built on top of Eclipse, does a terrible job at this. For a statically typed language such as Scala, it's aggravating when your tools report spurious compilation errors.
Saw some Scala at a conference recently. The guy was demonstrating using it to do TDD.
I lost track somewhere in the first ten minutes or so, but it looked like he was importing/using multiple DSLs and helper libraries. After I lost track of the exact details, I started scanning for the gist of what he was doing.
After an hour, he had what looked like the most massive clusterfuck I've ever seen in a project file -- all to do something that would take a dozen lines or so of simple FP script. Seemed like every functional thing he used was either also an object or had to be bolted into an object graph for it to work. The project file had scores of things in it.
This did not leave a good impression. It reminded me of when I saw my first C/Win32 app and realized you needed a couple hundred lines of code and several files just to say "hello world" -- except this was a couple orders of magnitude more complex. It was a god-awful abomination.
Not all Scala projects are like this. There's a sect that wants to write tests in "human readable" fashion, e.g. the people who like Cucumber in Ruby; in Scala those same people write their DSLs within the language, something Scala is good at and that I'd argue provides real advantages over an "external" DSL. But you don't have to do that; I write Scala professionally and all my tests are just ordinary JUnit test methods.
I'm okay with using DSLs. Hey, if you have good FP, flaunt it. My concern after watching this, however, was whether or not the JVM development environment itself encourages complicating things beyond the most minimum thing needed to solve a problem when you're using it in a functional manner. (I haven't done Java in a decade). So, for instance, could I have just written a simple 12-line script to solve the problem he was banging around? Or would I have to create some kind of object with a "main" method? Could I just add in a test file and write functional tests from there, aka JUnit, or do I have to bolt something in that then requires a separate project structure and so forth (aka JUnit)
There's no right or wrong answer for any of these types of project configurations. Heck, I like my tests in a separate project. It just looked like every time he had a new need, the project got 14 times more complex. The solution to one problem made the entire development environment more complicated for everything else. That's heading in the wrong direction, no?
Admittedly I only had a brief glance. Thanks for the answer!
I've used Scala on and off professionally for about 4-5 months and the best advice I could ever give to someone using it for the first time is to try and treat it like Ruby but with type safety.
As numerous people before me have said, the language is a mess. Although it offers some benefits, the syntax is so absolutely bloated that you're probably better off taking the time to really consider whether or not you absolutely need it for all of the headaches and unreadability you're going to run into in terms of code. There aren't many Scala developers out there and the learning curve can and likely will punish you when things need to get done, assuming you're bringing in new developers.
The open source libraries all generally seem to have glacially slow development processes, which in some cases might be considered acceptable, but when the main Scala team pushes out 2.11.x (and to some degree actively encourages its use) and X framework you're using literally cannot run because library Y is not compiled against it, you end up stuck on Scala 2.9/2.10 which is really unpleasant for you because you're missing out on the speed increases and other quality of life improvements (how many times have you run into the 22 argument limit for case classes on 2.10?).
Perhaps I'm asking for too much, but Scala strikes me as a language that's supposed to be moving a bit faster than Java in terms of development, but that doesn't really seem to be the case. All in all, while it has some neat parts, if I never got to work with it again I wouldn't be crying about it.
For Haskell at least, the GHC runtime is getting pretty good, and seems to have at least basic tools for GC analysis etc. I'm ignorant of MLs so perhaps someone can speak to their status.
Of course there's the much-touted "Java Ecosystem" but it's looking crustier than ever methinks. Maven?? Blech! Also, it doesn't seem wise anymore to build a website on Servlets/JSP/SpringMVC etc, esp. if you want to attract devs. Rest APIs maybe.
What's the killer feature these days recommending the JVM?
Do the Oracle or OpenJDK JVMs deal well with heaps that large? I have no interest in other JVMs because my employer would not consider switching and I can't say I blame them.
It depends on what you mean by "deal well with heaps that large". You can certainly set them that large with no problems. But given your memory patterns they can cause dramatically bad GC times.
I enjoyed Dr Ordersky's course (of course, it's based largely on SICP, which I also enjoyed), but there's a world of difference between the code you write for those exercises and the code you write in the real world.
I'm on record as being a Scala skeptic; I've already run into things that the type system seems to encourage but causes headaches, and the size of the language means that no matter how small a subset you write yourself, you can't help but page out when someone else's subset is different than yours. I know that C++ or Perl wizards eventually get to the point where this isn't a problem, and I guess that Scala is positioning itself as Java++, so the same caveats apply.
You still have to put code inside an object, but it's two lines of boilerplate rather than Java's 8 or so:
object MyApp extends App {
code here
}
I tend to use Maven to build my projects, so test classes have to go in src/main/test, have names ending in Test, and have their test methods annotated with @Test. But there's nothing to stop you making another App that just runs tests when it's executed, if you want to do that.
Things should be orthogonal, and that's usually something Scala is very good at, e.g. the way (scalaz) Futures are handled is IMO a very elegant balance between exposing the difference between sync and async code and not making it too cumbersome to use.
Here is some actual test code, based on scalacheck:
property("to and from file") = forAllNoShrink(genArrayForSeries)( data => {
withTempDir(f => {
val (stagingDir, dataDir) = mkdirs(f)
val s = SequentialBinaryV1Storage(dataDir, stagingDir)
val id = SeriesIdent(UUID.randomUUID().toString)
val oldSeries = BufferedSeries(id, data._1, data._2)
s.write(oldSeries)
val newSeries = s.read(id).get
((oldSeries.ident == newSeries.ident) :| "identities do not match") &&
((oldSeries.data == newSeries.data) :| "data series do not match")
})
})
Not much DSL, though there are a few helper functions handling stuff like creating a tempdir for the test and deleting when finished.
Scala is going to be generally more concise than Ruby (which I think most consider fairly concise).
So the impression I get from your comment is that this was a fairly large and/or complex project he was attempting to demonstrate. Maybe it just wasn't real appropriate.
Does the syntactic diabetes really bother people? Like, yes, these are different sequences of characters that mean the same thing, but visually it's very clear that they are the same thing; it's not the perl "there is more than one way to do it" where the ways of doing it are conceptually very different. It seems no different from complaining that I can write f(a, b) or f((a), (b)), which is a choice you get in almost every language.
Implicits are dangerous, sure. Typeclasses are vital and extension methods are nice, but it might be better to cover these use cases with something more specific. That said, these days the IDEs flag up implicits so it's not really a problem day-to-day.
Concise really helps readability at the function/module level - there's a huge drop in readability when a function reaches the point that you can't fit it on one screen. It may well be that the 1-line scala version of a method takes exactly the same time to read as the 10-line java version - but if it means you can fit your whole class on one screen, that's still a win.
Symbolic method names are bad and I wish the community would move away from them.
The definition of ++ is perfectly sensible once you stop panicking and start actually reading it. As is the parser; sure, it's a DSL, it uses some short symbols, but I defy you to find a better way to express the parser given. When you're building up a complex parser, it's well worth having a concise notation.
jsonFormatX are legacy cruft. In a modern json library you can avoid them by using Shapeless instead; hopefully spray-json will do this too.
The .toSet() example is deprecated and will give a warning if you actually try and run it.
Java-8 style lambda compilation is already available under an experimental flag, and the next release will have full support.
Syntactic diabetes is to me the best warning sign.
It means the focus on orthogonality has been lost somewhere in the evolution of the language.
There should be only one way to express a given language operation, and this way should be the simplest and most elegant. Not just because of aesthetic (which is crucial when speaking about readability), but also because it would combine the most harmoniously with other parts of the language.
It seems to me that at this point scala should deprecate all non-essential syntactic sugar and features and reduce the language to its "core". Or, at the very least, people should
start a fork with that goal.
Hell, it could even be just a compilation option.
> There should be only one way to express a given language operation
This is not possible in general, because concepts rarely coincide cleanly with syntax. For example, you can't have both currying and closures if you insist on this.
Most of the "syntactic diabetes" examples in the talk are of this kind: They are actually separate, general concepts that happen to overlap. And some don't even overlap, but the author does not seem to fully understand the language.
For example, that you can write both f(x) and f{x} is simply because f{x} is essentially the same as f({x}) and the parser allows you to drop the parentheses if they directly surround braces. But `{x}` and `x` are not the same: the first is a scoped block, the latter is a variable. You cannot use a variable to express a scoped block and you cannot use a scoped block to express a variable.
There IS unnecessary conceptual overlap in Scala, but you can find that elsewhere: For example, there's quite a bit of conceptual overlap between view bounds and type classes. But it's difficult to blame the language for it: much of this conceptual overlap exists to make the Java interoperability story less painful (of course, you could argue that Scala shouldn't try so hard to be interoperable with Java at the cost of language simplicity, but there are tradeoffs either way).
I don't see how it's a loss of orthogonality; just like a whitespace-insensitive language, it's saying that the choices of bracket and dot are syntactically equivalent. And that syntactic freedom means the precedence of a Scala line is often much clearer than the equivalent in other languages:
a b {c d (e f g.h(i))}
In Haskell you'd have to write that as something like:
a b (c d (e f (g h i)))
//or alternatively
a b $ c d $ e f $ g h $ i
I find it much easier to visually tell what the tree structure (AST) is in the Scala version, because of the different possible delimiters -the fact that a '(' must match a ')' and not a '}' makes it much easier to visually parse.
> Does the syntactic diabetes really bother people? Like, yes, these are different sequences of characters that mean the same thing, but visually it's very clear that they are the same thing; it's not the perl "there is more than one way to do it" where the ways of doing it are conceptually very different.
Oh yes, this is one of the things that bother me the most about Scala, actually. I don't mind if there are conceptually different ways of achieving the same goal, as you put it, because those different ways usually have different trade-offs; if you're doing things one way instead of the other, you know why you're doing it, there's a certain benefit in doing it this way.
But syntactic diabetes is bad because it ultimately provides no real benefit. Different people will write different code based simply on their tastes and preferences and pretty soon you'll have a mess in your project codebase, unless you enforce strict rules and conventions about writing code. Furthermore, people who work in a team that enforces one set of conventions may have trouble when joining another team that uses a different set of conventions.
In Java, for example, this is not the case. Yes, there are things that the language itself doesn't enforce, and conventions are used, but these conventions are well known, and there's probably no Java developer on Earth who wouldn't adhere to them. When a totally new Java developer joins the team, she can usually read code right away, because there are no surprises with regards to the syntax. Sure, she'll need to spend some time perhaps to really get what's going on, because the code might be complex, but the syntax itself won't stand in her way.
> But syntactic diabetes is bad because it ultimately provides no real benefit. Different people will write different code based simply on their tastes and preferences and pretty soon you'll have a mess in your project codebase, unless you enforce strict rules and conventions about writing code. Furthermore, people who work in a team that enforces one set of conventions may have trouble when joining another team that uses a different set of conventions. In Java, for example, this is not the case. Yes, there are things that the language itself doesn't enforce, and conventions are used, but these conventions are well known, and there's probably no Java developer on Earth who wouldn't adhere to them. When a totally new Java developer joins the team, she can usually read code right away, because there are no surprises with regards to the syntax. Sure, she'll need to spend some time perhaps to really get what's going on, because the code might be complex, but the syntax itself won't stand in her way.
But the brackets, braces and dots are just such a trivial part of the syntax. Is anyone really getting confused about the difference between
It's actually worse than that because one method application that takes an argument can return either an object that can have a method called on it, or a function which can be immediately applied, or some object that doesn't have the appropriate method but can be implicitly converted to one that does - so without knowing the implementation, there is no unique translation of that string into method calls and objects. Your IDE will probably italicise random words in your DSL code for no obvious reason.
A separate issue is that without knowing the implementation you can write code and not know when or how many times it will be evaluated, because if you pass it into an argument that argument may be call by name.
What it all adds up to is that you can look at a piece of code and have very little clue about what it is actually doing underneath. And what is much much worse - it's usually a leaky abstraction so you actually need to know what it's doing underneath and this happens all the time in common libraries in the name of providing a nice DSL.
The ONLY time it makes sense for me to drop . is for some DSL stuff and some math operator stuff...
But really - this is why you have a style guide. Make your style guide say "Always use . unless a math operator". Then the guy that does
foo map x + y filter < 2 foreach println
gets bonked in the head and told to rewrite it.
You would do the same in Java to the guy who wrote a 600 line method, right? Should the JVM enforce the no 600 line method rule, or can we deal with it in style guides? Because the 1 time I need to write a 900 line method, I am sure glad the JVM doesn't limit me.
In my IDE I'd have no trouble - they show up in different colours.
I kind of agree with you, but I think the flexibility over delimiters actually makes it easier to keep code like this clear - you can write something like
opt.foo{ bar.baz(buz bif baf) }
And it's very obvious which brackets go together and what's at which level of nesting.
It won't be able to figure out the non-delimited version in the parents example. That's the point. By allowing that you've made it harder to read unless the reader has exactly the capabilities of a heavy weight IDE. This may or not be an ok trade-off, but you have to accept that there are cases where people may be reading your code without that benefit.
> It won't be able to figure out the non-delimited version in the parents example. That's the point. By allowing that you've made it harder to read unless the reader has exactly the capabilities of a heavy weight IDE.
Yes it will. This is not Haskell where different functions have arbitrary precedence; Scala functions are evaluated left to right (except a very short list of mathematical operators) unless they end in ':'. The only possible meaning of "a b c d e f g" is the one where b, d and f are methods and c, e and g are arguments. You don't need a heavyweight IDE to work that one out.
2) You've moved the goalposts. The original parent said that he found the call syntax confusing, you responded by saying your heavyweight IDE prevents that confusion from happening, and I pointed out the tradeoff required for that. Now you've gone back and just said it isn't confusing and that it is something you have "to work out".
The fact is, some Scala developers find the call syntax confusing and some Scala developers read Scala code in editors that do not have the power to help them suss that out. That is a cost to the flexibility in call syntax. Is that cost worth it? For some people yes, for some no, but don't deny the cost.
1) Fair enough; I'm very surprised, and will take a look at fixing that. 2) I didn't mean for the user to work it out, I meant that a simplistic highlighting script should be capable of it.
I don't think anyone's getting confused but I do think that having four different ways to write essentially the same thing can lead to inconsistent code. And when you have a large project with lots of people working on the same code and with people coming and going all the time, consistency matters.
Scala has some great ideas, but it's so easy to abuse it. I know, I know, you can shoot yourself in the foot with any language. But there are languages that have several safety mechanisms you need to circumvent in order to be able to shoot yourself in the foot, and then there are those that give you a gun and a book called "How to shoot yourself in the foot".
The author seems to think that java 8 lambdas are faster than scala lambdas. This isn't strictly true. Java 8 spins the inner classes for lambdas at first use, this gives them a performance boost at startup (loading tons of tiny classes from a jar is painfull for the jvm) but at runtime they perform the same (it's just invokevirtual). Another optimization that java 8 has is that lambdas that don't capture are cached & reused, scala does the same if you use the -optimize flag.
Maybe, but it's just a generic statement about programming, it has no real value in a critique of Scala specifically. Part of the beauty of any flexible language is you can go back and refactor it down to a more elegant solution as you learn more. That doesn't mean you have to boil the code down to a point where it is largely impossible to read any more in Scala than any other language.
There are real pain points in Scala when you try and scale it from single developers to teams working on a project and most of them are to do with the flexibility of the language.
I think all companies working with Scala end up settling on a sub-set of the language that they are happy with. In that sense, the bad is irrelevant: you are never put in a situation where, say, you are forced into using implicits (apart from light use in external libraries like lift-json) so if you don't use them you never suffer their downsides. If you obsess over parts of a language you don't even have to use... then well I'm afraid I have nothing but scorn for people like that.
At team-scale then your main pain point is trying to get style of writing that everyone can get behind. Code reviews can be painful when developers with different ideas on how to solve a problem butt heads and pull requests turn into "That's not how I would have written it" instead of critiquing the actual code presented.
The tooling and compiling I completely agree with. SBT is a horrific mess. I don't have a single good word to say about it.
>
Maybe, but it's just a generic statement about programming, it has no real value in a critique of Scala specifically.
About Scala specifically? No, indeed. About languages which make it possible to create custom ASCII operators? Certainly. I don't know how the Scala culture about this is, but my experience with Haskell is that once people run with it, you get awful ASCII DSLs with cryptic operators all over the place.
> I think all companies working with Scala end up settling on a sub-set of the language that they are happy with.
So, pretty much like C++, a language that people love to hate. The problem is that, out in the wild, you're going to end up with legacy code made by people who picked a different sub-set.
There is an infamous library called dispatch. Someone put together http://www.flotsam.nl/dispatch-periodic-table.html to try and help other developers out when using it. I use it because it is good... but hell. The lack of discipline there is awful.
The problem is that, out in the wild, you're going to end up with legacy code made by people who picked a different sub-set.
This is the situation I've been in for the last year and I agree that for every point I make in praise of language flexibility this is the strongest counter-point.
Dispatch is a library that I initially found irritating, because in early versions it proved extremely opinionated in it's use of futures and symbolic operators.
However, as time has gone on, I've found that my coding style in Scala has evolved to the point where I want low-level libraries to work in an asynchronous way. There are now also overloaded, human-readable methods for most (if not all) of the symbolic operators.
> About Scala specifically? No, indeed. About languages which make it possible to create custom ASCII operators? Certainly.
IME, its possible to be just as unreadable with the more verbose custom alphanumeric operators (functions/procedures) that every structured/OO/functional programming language lets you create as with terse non-alphanumeric symbolic operators; all that eliminating the latter does is to limit how concise [1] it is possible for even a well-designed DSL to be.
[1] Note that concise isn't just terse, but also clear.
> I don't know how the Scala culture about this is, but my experience with Haskell is that once people run with it, you get awful ASCII DSLs with cryptic operators all over the place.
Yes, that happened in Scala too. Luckily another set of Haskell slingers wrote us Scalaz, so it's not all bad.
In its early stages Rust used to employ a lot of sigils (people joked that its a language which makes full use of all the keys on the keyboard), but the language has moved away with the cryptic operators and IMHO looks cleaner.
AFAIK, the sigils were used to express differences in data types (wrt to memory allocation scheme), which is quite different from ASCII operators. This doesn't bother me nearly as much, but it may be my Perl background.
You are right, they were mainly around pointers. As long as they are a handful and their meaning doesn't change (as opposed to using in a DSL), its easy to get used to them. Still, I find the explicit keywords a familiar territory and better to read.
Well, except the difference in definition between between "terse" and "concise" is that "concise" does mean easy to comprehend (and, in the context of a written medium, easy to read.)
The first thing that I actually thought about when I read this was junit hamcrest matchers, sure it's concise but I don't consider it readable at all. The limited expressivity of java really gets in your way.
With scala you can write test that are concise and readable with ScalaTest or ScalaCheck. The readability largely depends on the quality of the library that you use but also the user.
Yes, scala. I'm having some fun with it... but i'm also having a lot of arguments with it. I especially recognise the parts of "there is no best/single way of doing things". I can overcome the syntax diabetes.
I'd like to do functional programming, I'm doing server/web based stuff mostly. I'd like the language to have a big(large) ecosystem. Clojure is fun and all, but it's more or less a hackernews language. There are only a few serious businesses using it. It also lacks a web framework like Play!. Same goes for Haskell. So besides all the bad stuff of scala, having play and quite a large ecosystem is why i wanted to try it.
Your way of educating people about Clojure isn't particularly helpful. Don't make sure that people miss out a really good language, instead take this opportunity to share [personal experiences or impressive writeups about] how awesome web frameworks are on this side of the grass.
I read the comment as condescending and as a reply to the parent commenter's lack of knowledge about Clojure and Clojure ecosystem. May be I interpreted it incorrectly and that's why I suggested to shine the light on the real picture.
Tbqh, my remark was pretty condescending, because the original comment seemed to be suffering from the DK effect.
In fairness, there's a kernel of truth in that almost any article about Clojure seems to get uncritically upvoted, but that's another matter. The fact remains that Clojure, whilst not as popular as Scala, is nonetheless (quietly) in use at a lot of firms.
Some more examples:
* CitiGroup EU FX derivatives is pure-Clojure
* There's at least three different hedge funds using it.
* Deutsche Bank are definitely using it too.
You should try Luminus, which concentrates all the basic libraries for web development.
Not as rich as Play! or Django but sufficient for doing a lot of things. It's also a great way to learn Clojure smoothly, it's far more accessible than Pedestal for a beginner.
Pedestal client has been retired. Pedestal server is a high performance server framework that most people probebly want have to use. Pedestal gives you much more power offer use of threads and how you do controll flows between middlewares and such.
I actually might give Luminus a go if I give up on scala sometime. Thanks. I did have some fun with clojure, it's much easier to get started with.
I know i'm kind of spoiled with features because I do a lot of projects which involve django. I do not expect a framework to be as rich as Django. But i prefer having some things integrated. Some might prefer choosing every component in a framework (ORM, url routing system, form validation etc), but when you work in a team or with freelancers, it comes in handy if theres just a way of doing things.
With a type system that's weaker than Java's? Look at e.g. the way spray handles HTTP headers; it eliminates a bunch of errors that are in some sense trivial, but almost all bugs are trivial when looked at in the right way. You just couldn't do something like that in Go.
Look at e.g. the way spray handles HTTP headers...
For those of us not familiar with Scala it'd be interesting to see you expand on that statement. Are you talking about the type definitions in this file?
and the header and its parameters are typed, and so if you make a typo in the name or the value (or try to pass the value of one header to another) then you'll get a compile-time error.
You could type things like headers in Go too if you want to, by introducing a new type for each header in a similar way, get them to check values are valid on being assigned etc. (std lib does it in a simpler less robust way but it's quite possible). Go could then do compile time checking for those types, e.g. something like:
Hah, true enough. But the other half of what makes Spray work is the high-level abstraction possible, which makes it easy to handle these different things generically. Consider e.g. https://github.com/4lex1v/Sprayed/blob/master/src/main/scala... , which is an example of abstracting a possible "context" for a value, with implementations for futures or possible errors (both things that go has direct support for, but it's much less clumsy to work with these things when they're just ordinary objects that follow the ordinary rules of the language). You can abstract over those contexts, writing one method that can handle a list of async calls or a list of possibly-failing calls. You can extend it with your own data types, e.g. you can do session-in-view in a principled way, using ordinary language features rather than magic annotations, by having a context that represents "database operation".
I would imagine having union types and such would make something like this a bit more powerful. Not entirely sure, but having a hierarchy of http contentencoding types, and http error/success types could make it easier to write code that handles all error conditions. Also having a type for sanitized strings versus unsanitized strings. That being said, I've never used a language with a sophisticated type system to do web programming.
Well, if you want to do functional programming, as the OP indicated, then Go is not the way to go. Scala seems like a fine choice then, or e.g. Haskell if you want to go all the way.
It's a play on the term "syntactic sugar": Too much syntactic sugar leads to syntactic diabetes. And syntactic sugar generally refers to language features that allow you to write things in neater ways. It is always possible to "de-sugar" such constructs by writing them in a more basic way, which is usually less neat. Examples would be e.g. list comprehensions, for .. in syntax, x += 1 etc.
It refers to the fact that there are many syntactically-equivalent ways to express the same code. Slide 11 shows expressions that evaluate to the same thing.
I use scala a lot and it did become my go to general purpose language (as well as my workplace adopted it as a first class citizen and used for many new projects)
I do have issues with it, but mostly with developers using (abusing) it. (And library authors that are a bit religious about the functional paradigm and simply love their operators...
With great power comes great responsibility, the is no better description to this language.
Also, I was looking at the CanBuildFrom hell with fear, but Odersky et al's book on Scala surprisingly did a good job getting the pieces in place for me. It even makes sense of the madness.
Finally, Bozho is one of my most respected contributors on stackoverflow. And I can say that his slides actually do justice to Scala, I might disagree on the conclusions, but the facts are absolutely right.
I kinda agree with this. Scala has good bits. Very good bits. Gorgeously beautiful bits, even. But the ugly bits are so terrifyingly ugly that I dare not touch it.
Give me the Scala pattern matchers (that can also match by type and even by content of case classes, I believe), with the case classes and the actor concurrency model, but keep the horrendous type system and the confused parts of the syntax.
The article shows some examples where you can choose between regular brackets or curly brackets. There's a lot of different ways to say the exact same thing. Why? Which is best? Are there any cases where one works but the other doesn't, and if so, why does the other exist? But maybe I'm too used to different brackets meaning different things. I'm used to Java and Groovy where brackets are used very consistently.
The type safety goes way overboard with extremely arcane, incomprehensible expressions. The excessive power of the type system makes compiling far too slow. And the pattern matchers mean you can easily get your type back when you need it. I really strongly prefer the more dynamic approach of Groovy. Total type safety is a trap.
> The article shows some examples where you can choose between regular brackets or curly brackets. There's a lot of different ways to say the exact same thing. Why? Which is best? Are there any cases where one works but the other doesn't, and if so, why does the other exist?
Yes, but which one would you remove?
If you disallowed the curly ones, developers would suddenly require an additional language feature to define methods which could be used like this:
using(someResource) {
// do something with ressource
}
Apart from that {} has semicolon inference, while () doesn't. That's extremely helpful, if you have some expression and really want to make sure that it can't be split into something like { doThing1, doThing2 } by an unaware developer.
> Total type safety is a trap.
Sure, there are limits on what can be done with a type system, but these options have been growing larger and larger in the last decades.
I wouldn't throw away the last 40 years of progress in that area and start doing stuff manually which any decent compiler can figure out for me.
> Groovy
I haven't heard from Groovy since a long time ago. Is it still actively developed? The last things I saw was that they were struggling to catch up, and work on the new MOP still wasn't finished.
On the Gartner PLI, Groovy is way down on position 20. That doesn't look too promising either ...
> I haven't heard from Groovy since a long time ago.
It's still the sole language used in Grails, which is losing adoption share to newer web frameworks. Gradle is on the rise, but Gradle will probably soon open its configuration as an API so any language can use it, so Scala and Clojure could become more popular for scripting Gradle in the future.
> Is it still actively developed?
There's a technical developer employed by Pivotal who's presently working on making Groovy work on Android. I don't know if he's working on it full-time or merely squeezing in development between fee-paying consultancy work.
> The last things I saw was that they were struggling to catch up, and work on the new MOP still wasn't finished.
I don't think work on a new MOP has started. It's pitched for Groovy 3 and the next version of Groovy is still version 2.x.
> On the Gartner PLI, Groovy is way down on position 20.
On Tiobe, it's still hovering around position 49, where it's been fluctuating since 2007, sometimes higher, often out of the top 50.
Odersky's Coursera is excellent. For me, it was vital to jumping the gap from "Here is a language that gives you a million ways to solve problems" to "I want to express this particular concept, so I designed a language well suited for expressing it".
Heh ... it is the other mainstream "hot" language.
I was looking for a language to move to post-python. I love python but the 2.7->3 jump has been annoying. More than that, I felt I needed static typing for the next big system I did ... too much pain debugging python.
I looked at Scala since it had the JVM behind it. While the language seems decent, it seems too easy to write unreadable code. Multiple ways of doing the same thing ... yada yada.
Friends at Google had been espousing Go for a long time and I didn't bother. Seemed like a proprietary language with little adoption. Two things changed for me. I got some exposure to erlang via elixir. This made me think about the whole channel concept. Second, I had to read code in Docker (which is awesome). I learned a bit of the language and was surprised how small the language was. Really reminded me of C, which I love. There seems to be more adoption of Go .. e.g. Cloud Foundry and others. I like Go enough that I will be spending more time learning and investing in it.
From the looks of it, the author of these slides has written very little Scala. Take slide #7, for example, where he writes def bar() = { "1" } when def bar = "1" is perfectly sufficient. Ironically, I may very well be pointing out the bad parts of scala (i.e. that () is simply a convention for indicating Unit or side-effecting functions, but its just convention and not enforced by the type system in any way). Notwithstanding that, I don't think someone who has written very little Scala is in a great position to offer a reasonable critique.
This is a longer discussion, but in the very first slide he points to the object-orientation as a plus. In my opinion, he's already wrong. "There is no such thing as Object-Oriented programming." See: http://blog.higher-order.com/blog/2008/12/04/no-such-thing/
Specifically:
- Code on slide 3 has typos. (Yeah, that's minor)
- Lambdas are slower than Java 8 -- that's because Scala currently supports Java 6+. Java 8 has been released for 6 months. This is a ridiculous complaint.
- Heavy in terms of concepts -- another ridiculous complaint. If you want to keep on writing Java, keep writing Java. If Scala didn't bring new stuff to the table it wouldn't be interesting.
- Implicits -- agreed they can be misused. Type classes are the way forward.
- I don't understand many of the "very ugly" complaints. Yes, collections have lots of methods. Is this surprising? Yes, library code may be written in an abstract way. So what? Yes, DSLs look like DSLs. Yes, abstracting over arity is a problem in all statically typed languages. etc.
There are valid complaints to be made about Scala. I feel this talk demonstrates a lack of understanding of the language, and many of its complaints are in fact misunderstandings.
To me the biggest issue this talk reveals is that if you come from an OO background (which I assume the author does) then learning Scala will require a change of mindset. I don't think it is fair to make this a language complaint though. Scala makes it fairly obvious what you're getting yourself into and, as I said above, if you wanted to keep on writing code the way you have in the past it's not clear why you are using Scala in the first place.