Why Scala seems difficult but really isn’t
markusjais.com
markusjais.com
The perfect Java replacement would have - local type inference, less verbosity (e.g. public by default), full closures, anonymous blocks, no generics, special syntax for arrays and hashes, operator overloading and the ability of a variable to behave as if dynamic (e.g. leveraging the future InvokeDynamic). I would also completely purge checked exceptions and also get rid of the general syntax for anonymous classes - basically get rid of anything not useful.
People actually liked earlier versions of Java. It was a simple language, while still a lot more productive than C++. They fucked up its evolution and IMHO it's pretty sad that people like Scala so much; it just shows how low are the standards.
"local type inference". That's Scala. List(1,2,3)
"less verbosity (e.g. public by default)". That's Scala. def myMethod(arg:Int=1, arg:String="myDefaultValue") ... with no boilerplate crap.
"full closures". That's Scala. val myImmutable = { runThisCode }
"anonymous blocks". That's Scala.
"no generics". That's-- more or less Scala.
"special syntax for arrays and hashes". That's Scala.
"operator overloading". That's Scala.
"the ability of a variable to behave as if dynamic". That's Scala.
"I would also completely purge checked exceptions". Scala, so long as you stop writing try catch blocks.
"and also get rid of the general syntax for anonymous classes". Scala.
Look, I just recently rewrote a ten-thousand-line Java web app into Scala. I got-- no joke-- 75% code reduction, and the only reason I didn't get more was due to the fact that I decided to stick with Struts2 instead of moving to Lift.
Think of your typical method that accesses a Hibernate named query, and returns a boolean as to whether or not that item exists.
Here's the Scala version:
def domainExists(domain:String) = Option(HibernateUtil.getSession.getNamedQuery("domain.findByName").setParameter("name", domain.trim.toLowerCase).uniqueResult.asInstanceOf[Domain]).getOrElse(new Domain()).id > 0
That's a one-liner, and I'm sure there are Scala experts out there who could reduce that code even further.
public boolean domainExists(String domain) {
return Option.of((Domain) HibernateUtil.getSession().getNamedQuery("domain.findByName").setParameter("name", domain.trim().toLowerCase()).uniqueResult()).getOrElse(new Domain()).id > 0;
}Also, I would like a language that's as close to the JVM type system as possible, yielding the same performance as Java in all instances (including on Android, where Dalvik doesn't have the same GC and optimization characteristics).
"no generics". That's-- more or less Scala.
Generics are an inherent part of what Scala is. Surely it takes care of some gotchas, but I see many code samples where I feel like puking.Generics weren't really meant for languages without Hindley-Milner.
"the ability of a variable to behave as if dynamic".
That's Scala.
Scala is not dynamic by any stretch of imagination, no matter how much wishful thinking you can incur because it has structural typing -- I see this notion flying by all the time, but people generally don't know what they are talking about.E.g. you don't see people saying this same thing about Haskell, when compared to Lisp, even if Haskell is even more concise than Scala, taking structural typing to extremes.
What I mean was that I'd like something like the dynamic types in C#.
Unfortunately, for now it is an experimental feature. But thanks for pointing it out, it seems that it's coming :)
Sorry, but that's the most ass-backwards point I've heard. The language provides too much power and flexibility, and you want to be locked into one specific format, syntax, and the subsequent reinventing-the-wheel nightmare that causes most projects to go horribly over time, budget, and stress levels?
The language subsetting issue is a huge problem, c.f. C++. The complexity of Scala makes it very difficult to understand a lot of library code, even if you're quite competent in it. To keep code for a large code base manageable and understandable, most companies will end up defining the "allowed Scala" in a coding standard. This is a failure of the language, IMO.
Personally I find myself much more productive in Scala for anything non-trivial than in any other language.
Take your Java code, remove almost all the type info, and add some nice syntactic sugar for singletons. That's beginner Scala, and it's already worth using. The rest of the language is just gravy.
Ahem. http://groovy.codehaus.org/
The #1 feature of Groovy in my mind is that there is almost no learning curve whatsoever. All Java code is already Groovy code - you can learn all the dynamic tricks as you go.
Sorry, commenting before morning coffee :)
Meanwhile, Groovy uses Java collections.
http://www.scala-lang.org/api/current/scala/collection/JavaC...
And it has same performance as Java
It severely beats Java, but it falls pretty far short of Clojure, in my opinion.
agreed!
I know things like type erasure and other programming language bits and bobs upset the PLs gurus, but I really don't care about that. I can write concise code that looks like a dynamic language, but get full static type-checking. That's a huge win.
I really just don't understand it.
* Eclipse support is spotty. Apparently legal programs suddenly develop lots of errors. Sometimes restarting Eclipse will allow the program to run anyway.
* Types are constantly getting in my way. Sometimes types are correctly inferred, sometimes I need to add types to hint the compiler about what I'm doing.
* Writing anonymous functions remains hit and miss. I just throw in underscores at random until something works.
* I don't understand where the round or squiggly parentheses go in for comprehensions; i.e. what goes in the parens and what stays outside.
* Hashmaps have a cool "+=" operator to add a key-value pair. So why does "put" work but "+=" doesn't? Another mystery.
* Sometimes the parentheses after function invocations are optional if there are no parameters. Sometimes not. Why?
It's not Scala's fault that the Eclipse plugin is less than perfect, it's already very powerful. As for my little struggles with the language, none of this is witchcraft; I'm sure there are well-defined rules and sensible answers to all these questions and many more. But I must say I'm annoyed with the huge number of rules behind Scala. The amount of stuff I need to learn to really use Scala effectively is daunting.
Contrast this with my Ruby experience. This is a language that places great value on orthogonality: wherever possible, every operation works the same in every situation. So you have a smallish number of versatile functions, not too much stuff to absorb and things generally Just Work (TM). I taught myself Ruby and Rails and wrote my first useful Web app in a couple of weeks' worth of evenings, and it was a very pleasant experience.
Clojure, similarly. All the parentheses took some getting used to, but the language's syntax is wonderfully simple and consistent, so getting stuff done is mostly just a matter of looking up the most appropriate function in the cheat sheet. I managed to be productive (for small programs) with Clojure in a couple of days.
Scala is no doubt a fantastic language. But thanks to its kitchen sink attitude, it's not an easy language to come to grips with for someone with an aging memory and a less than full-time commitment.
Perhaps this is one of the things that is tripping people up that I'm not doing. I tend to still be quite verbose in my code, even if only as a way of reminding myself what I thought the code was supposed to do (ever look back at Python and you're not really sure whether the variable is supposed to be a list or a tuple or a string? I have that problem all the time). I don't tend to use all the flourishes like underscores and such.
It seems a bit like Perl's many ways to do it attitude. Except I feel like Perl was designed by ideology, whereas Scala has a lot of bits and pieces because it wasn't clear to Odersky et al. which bits people would like and which they wouldn't. Perhaps rather than trying to enforce an idomatic style, they wanted programmers to find their own way. But that means there's things in the language that exist and can't be taken out (XML literals), and there's no documentation cohesion (by which I mean different documents will tell you to do different things, and you're not sure which is best).
If you Google "effective scala", you'll see a number of people clamoring for a book along the lines of Effective Java, and Scala sorely needs it, but Scala is still too much of a moving target to warrant putting anything in dead tree form yet. The Davetron Scala Style guide, however, is a really good stop gap, and helped me a lot.
As for type inference, another week of programming and you'll fall into a groove where you're anticipating when you need to declare types and when you don't. I had the same pain, and after a week, it had dropped down to a very occasional annoyance. It might just be my programming style, though -- I declare the return types on all functions that are meant to be called from another class or object, so there's a lot of information for the compiler to work with.
I agree about the underscore thing. It's pretty useless, and Clojure's version looks superior to me. As best as I can tell, the underscore doesn't work inside an extra layer of parens or curly braces. But it's just syntactic sugar, after all. Using a named variable isn't the end of the world. It's just three extra non-whitespace characters, "n =>".
http://blog.tmorris.net/anti-intellectual-euphemisms/
Specifically:
> using the word complex, unnatural, academic, “your world” or unintuitive to mean “I am not able nor am I willing to invest the effort to come to to understand this.”
Other than those people:
The blog author I quote above is one of the many "PL gurus" you speak of that rip into Scala because of its various deficiencies when compared to the likes of Haskell. The ones I am smart enough to understand mostly revolve around the type inference and type erasure problems. You mentioned those but I have already run into issues where I did care about them so I don't think its fair to dismiss them as you did.
The amount of hyperbole that comes from elements of the Scala community on actors I think is a cause of a fair amount of vitriol, mostly because actors are not a silver bullet and come with their own host of problems. Akka is trying to solve some of those problems of course :)
And of course the lack of tools. It's hard for me to talk about this because I loathe IDEs. So far I have been writing my medium sized project entirely in vim + NERDTree and it's been great. I imagine with enterprise scale projects I would start to miss Eclipse though.
I can't learn a new language quickly, so to learn I'm blogging about my experiences at http://leftnode.com and trying to write as many small programs as possible, moving into larger ones when I'm ready.
I'm trying to ignore many of the larger projects and in-depth Scala projects for the time being so I don't overwhelm myself and give up on learning the language.
I loved scala when I was writing and reading my own code, but it started to feel like perl when I had to use and dig through other peoples code. This is a fairly superficial feeling, and I could be off mark, so take it with a grain of salt. I definitely plan to use scala again when I need the performance over jruby/clojure, in place of java of course.
Ruby code gets really clear when you understand "self", eigenclasses and closures.
Required reading: http://pragprog.com/titles/ppmetr/metaprogramming-ruby
Also, Ruby is not a functional language; but IMHO is much better and more elegant than many languages that claim to be functional.
I remember reading early Rails code and - bang - everything is obscure notation for class member of private class using the '@' symbol or something (along with eval expression that would clearly slow down everything and ... did).
1. I wish people stopped saying "static language that feels like dynamic". This is just a marketing slogan. Type inference is not a substitute to dynamic typing.
2. I know that coming up with a good, plausible code examples is difficult but it's not an excuse to give bad examples. House has-a Bedroom; House not is-a Bedroom.
3. > Scala has the best of both worlds: true multiprocessor parallelism and a powerful functional programming model
This sounds as if usually multiprocessor parallelism and functional programming are mutually exclusive and Scala finally managed to have the best of both worlds.
4. > v.foreach(println)
... eh, isn't this just passing a named function as a parameter?
I think Scala is an admirable and ambitious effort to allow oo + func programming on the JVM. I also got the impression that the type system is "good enough" for most DRY efforts. But then, my background in this area is virtually non-existent.
Depending on what sources you learn from, you don't need to learn all the intimidating language features in the beginning itself. I am currently working through [1] - well written, but slightly outdated. [2] is where I got oriented initially.
It's also great that they do well to come within striking distance of Java in performance (this is not my impression of Clojure). Another super cool approach seems to be that of Mirah (no special runtime, Ruby-like syntax).
[1]: http://www.codecommit.com/blog/scala/roundup-scala-for-java-... [2]: http://grahamhackingscala.blogspot.com/2010/12/guide-to-lear...
I'm rather sold on it, though. I've been warily learning it in dribs and drabs for about a year, and one of these days will actually write something that accomplishes a task.
People keep trying to sell new languages to Java developers using the JVM. The problem isn't the language, though, it's the JVM itself and the licensing problems, too.
My understanding of Scala is quite imperfect but the more I've learned the more it seems that it's got pretty facades built over weak wood. Rather than being a 'scalable language' it comes across like a fake town that was built as a set for a Western. Look at any beautiful concise code sample that they try to seduce you with and you find that any small change requires tripling the code size. Look at the chapter in the book on DSLs and the take-away is "don't try to build internal DSLs".
Be it looking at the profiler running on on a Scala program that uses actors or finding that I never quite seem to get away with not having to declare types explicitly, I have a facepalm event every hour or so working with Scala.
In my case, (2) has nothing to do with it. I'm quite familiar with functional programming, both in languages that support it well and languages that don't. These days even my PHP looks like LISP.
(3) is certainly true, and I think it has something to do with the cultural difference that @speckledjim points out.
Anyone who's got to work with Scala will definitely confront (4); if you're working in Java or PHP or some other commercially viable language you can probably solve a high fraction of problems by using Google and Stack Overflow.
If you're programming in Scala you'll have a lot more success understanding the fundamentals of the language. If, for instance, you need to access Scala objects from Java (particularly the super-prevalent ones like Option and List) you'll find that cookbook-style documentation is 100% AWOL. Go look at the scaladocs for Option and List, however, and you'll be calling methods on them in no time from Java.
If you insist on working with Scala, get a book and read it all the way through from the beginning, skipping forward when you don't understand something.
Look at the chapter in the book on DSLs
and the take-away is "don't try to build
internal DSLs".
Which book do you mean? Also, do you mind elaborating on why one should avoid building DSLs with Scala? In my own experience [1] I've found it extremely nice for internal DSLs.The assessment that Scala is a pretty structure built of weak wood is not too far off, at this point. Compared to other strongly functional languages--Haskell and ML, say--the type system is shoddy and limited. In part this is a frustration of maintaining objects on Java's terms, but also defects in the JVM: type erasure is a hair-shirt that neither of languages I mentioned previously have to wear. You can somewhat avoid the loss of types with manifest hacks, but it's shoddy business. Often you can't; note that Akka has a distinctly dynamic feel, being that certain messaging functions--!! and !!!--must return an Option[Any] even when the original message is well-typed. The system loses the type information at runtime!
Compilation speed is also an agrivation. It's a slower process than Haskell--not zippy to begin with--and comes with less result, to boot. All that said, I tentatively like Scala, especially if a project is required to run on the JVM. I find it to be an especially pragmatic language, if unbeautiful and not something I intend to use for long-term, exploration coding. A fine choice for a language to be used in anger, let's say, if the memory usage of the JVM is of no concern.
In Haskell, using typeclasses like Typeable, you get the power of keeping types in runtime, but the types are actually erased.
You are quite correct, almost all strongly typed languages perform some type erasure for efficiency purposes. The problem, as I see it with Scala, is rooted in defect in the JVM; the system looses type information and cannot verify at compile-time that all your types will be correct.
Please correct me if I'm wrong or have misunderstood you.
When Haskell targets x86, the x86 opcodes surely don't help Haskell verify that [[Int]] really has [Int]s in there, but it's not necessary because it is proven at compile-time. So I am a bit confused why Scala needs the JVM's help.
Now, consider the difficulty of Scala wherein it's possible to represent a compound type. Erasure ensures that only the first parameter in the chain is generated in the type-erasure step, destroying the meaning of the union. There are kludgy ways around this--wrapping, bundling up manifests--but in the end the JVM does not allow the transmission of necessary information efficiently. Manifests serve the purpose of maintaining parameter information at runtime, but do so at the expense of code cache space and stress system resources. PermGem exceptions are much more common, in my experience, when doing Scala work as compared to Java.
The shorter answer to your question is the JIT nature of Java combined with a byte-code designed not to maintain the information needed to generate all possibilities of machine code on demand. LLVM IR maintains such information for Haskell--when targeting machine code directly I believe this is achieved by static polymorphic compilation, but I could be wrong; Stack Overflow time?--and the CLR does the same for C# and friends. It's a JVM problem entirely. The JVM promises to perform any and all compilation but is unable to accept all the information needed to do so effectively.
They're able to make a language that sorta-kinda looks like plain English, except that it's based on structurally unstable idioms that would require the user to be familiar with all of the corner cases of Scala syntax if they actually want to use it.
What we need are special-purpose languages designed for creating DSLs.
Some languages are fashionable because they are neat. Some languages are fashionable because they have allowed people to ship products better and faster. Some languages are fashionable because of both.
I can definitely see how an individual or small team could build something fiendishly clever in Scala that's maybe 2,000 lines of code that does the work of 20,000 lines of code in some other language.
On the other hand, I'm not sure that systems 10x that size developed by bigger teams would succeed in Scala, and I fear for what happens when that 2,000 line Scala system falls into the hands of maintenance programmers.
There are a handful of commercial success
stories with Scala
Correction: There are a handful of commercial success stories with Scala made public. There are companies trying to solve hard problems with Scala that are not necessarily interested in language advocacy. small team could build something fiendishly clever in
Scala that's maybe 2,000 lines of code that does the
work of 20,000 lines of code
I actually provoke you to pick a language, any language other than assembler, and write a piece of software with both languages, of reasonable complexity (no micro-benchmarks shit), as concise as you can.If the source-code in Scala is at least 3 times smaller, I'll buy you a drink.
There are projects which are just bad, let's ignore those. Those which can be classified as maintainable, are well structured and object-oriented, they abstract implementations behind interfaces etc.
But, they are verbose. I could probably accomplish the same thing in about 3x less code using FP/declarative constructs.
Reminds me of Yegge's Kingdom of Nouns; it is a funny read if you haven't read it yet.
http://news.ycombinator.com/item?id=2679041
Is it safe to assume that would be 300k-450k if written in Java?