Hacker News new | past | comments | ask | show | jobs | submit login
On Scala (dehora.net)
111 points by yareally on June 19, 2013 | hide | past | favorite | 99 comments



Using Scala has been a breath of fresh air after 10+ years of (mostly) Java. Mountains of boilerplate (I'm looking at you getter/setter/constructor auto-generated code) become 2 or 3 lines, in some cases a 1 line class definition:

  class Foo(var x: Int, var y: Int, var name: String)
(Thats equivalent to 6 method definitions and a constructor in Java. Also, the possibility that you forget to initialize one of the fields in your constructor [which happens from time to time in most Java code] is removed)

It's not just about having to write less boilerplate, it's also about having to read less code and expressing ideas using functional concepts where it makes sense.

Critics like to complain that having many features makes the language complex. In practice Scala code is fairly straightforward, the extra features just mean that library designers have to power to implement some pretty amazing interfaces for you using these features. Most Scala code is pretty sensible, and it's nice to know that the extra expressive power is there when you need it.

This may sound like heresy but I find myself being more productive in Scala than in Ruby. Part of that comes for the self-documenting nature of static typing and clear interfaces (No more "what methods and fields does this Foo object that is being passed in to this obscure method have?"). This is a very useful property to have when reading other peoples' code. The tooling is surprisingly mature (IntelliJ).

In hindsight picking Scala as a better Java should have been a no-brainer.


There are much less complex but precisely as powerful languages out there (like Haskell). Scala's crazy amount of syntax is what makes me avoid it, not unlike C++.


Does Haskell let me use the many Java libs that are used extensively internally in many organizations (including mine)?


Terrible, terrible answer if you are mostly doing functional Scala. I've got a blog post that deals with this. Tl;dr: Java libs are good along as they are thread-safe or immutable; if they're not, you're looking at horrible side-effects where there shouldn't be any.

http://talesfromannoyance.blogspot.com/2012/05/why-im-lookin...

If you want reuse, you need to look at taking those parts and wrapping them up in SOA.


For many use cases OO Scala works just fine, functional code used where it makes sense. Our goal is to integrate with existing systems, not to seek purely functional code as a goal in and of itself.


I agree with the concept. My concern is what happens as your team grows to include others whose Scala background is more functional. There is a sense that they should be aware of the old way your code base is put together. Unfortunately things could go awry when they code new functional based code expecting functional based input.

Don't get me wrong, I like Scala. You just really have to watch its dual paradigm behavior when dealing with Java code


No, but that still doesn't excuse Scala's syntax.


We haven't had issues with Scala's syntax. Point is that Haskell isn't a viable option for most use cases.


Uhm, although I admit Haskell is a powerful language, there are quite a few things that Haskell can't express as clearly as Scala. E.g. Haskell can't express nominal subtyping.


Huh? How is:

    Monad m => Int -> m Bool
not nominal subtyping in action? Any type you create a Monad instance for will be accepted, so subtyping. You have to actually make it an instance of Monad, it can't just have the structure of a monad, so nominal.


Is it polymorphic?


Wait, are you saying you don't know anything about haskell at all? Then why are you making claims about what it can't express?


Right, I don't know much about Haskell (not actively programming in it), but I know that Haskell was not designed with OOP in mind and things like polymorphic nominal subclassing are not first-class there. There are also some things that Haskell's type system can't do e.g. the nice thing that Scala does with fold/map/reduce always returning the right type, even if it has to be a different type than the type of the source collection. I'd like to be proven wrong, Haskell is on my list of next languages to learn well ;)


Haskell's typeclasses (which are almost identical to traits) support polymorphic nominal subclassing just fine.

Haskell actually has whole program type inference (unlike Scala, which only does local inference), so fold/map will always return the right type as well, but you also get to not have to put types anywhere if you don't want to (including function signatures).

Scala's main advantage over Haskell is being able to call into Java.


> Scala's main advantage over Haskell is being able to call into Java.

+ a superior module system + better type classes (no global namespace)

But yes, if running on the JVM is no option, Haskell is a serious contender


I don't even know what anything in your post means. You are correct that haskell is not an OOP language. You are very confused beyond that point.


> Scala's crazy amount of syntax

Could you expand on that a bit?


First, I must say that I like the idea of the language. It has ADTs (case classes) and typeclasses (traits), a bit of type inference, can run on Android and isn't Java. It's just the baroque syntax that bothers me.

It starts from this [1]. Then there's case classes, _, optional everything (forgetting = in a function def can make it mean something else), the currying syntax [2] (sometimes it needs an arbitrary _ to break ambiguity), the imports (especially renaming), arbitrary rules on whether construction needs "new" or not, etc.

The fact that [3] is possible even though Scala is not an almost-no-syntax language (like Lisps and Haskell) concerns me. And it even has macros, but all of its very many language features aren't implemented as macros :(

1. http://en.wikipedia.org/wiki/Scala_(programming_language)#Sy... 2. http://brenocon.com/scalacheat/ 3. http://blog.fogus.me/2009/03/26/baysick-a-scala-dsl-implemen...


_ is a godsend for code conciseness; I'll accept that it comes at a complexity cost. I'd argue it's less confusing than Haskell's pointfree style (which is how you do the equivalent).

optional = in function definitions is legacy that will hopefully go away at some point. Optional brackets and braces are something most languages have (bwim you can usually bracket or unbracket an expression without changing it), so it doesn't bother me that scala has them in slightly more places.

Using _ for partial application of an object method is simpler than you make it sound; you always need it. That page misunderstands. I dislike the complexity but it allows UAP to work which is awesome; are there languages with a similar UAP and functions-as-values without requiring disambiguation?

Agreed that relative imports and renaming imports are evil bad and wrong.

Construction requires new; I think this is largely there because it's a major difference at the JVM level and some people care about knowing when it's happening. Personally I agree we'd be better off without it.

Macros are new and experimental. I suspect that if/when they gain acceptance we'll see core language features implemented using them where this simplifies (e.g. there's no reason for comprehensions and case classes couldn't be macros).


http://kotlin.jetbrains.org/ runs on Android and isn't Java.


How long ago did it reach v1.0?


It's ready when it's ready. There's no time commitment from JetBrains.

It is usable now even for production although the compiler is not yet optimized and the language is still evolving.



- [1] comes down to the idea of not having to build two separate concepts (namely, operators AND methods) with different syntax, different declaration styles, different parsing rules, ... into the language. Scala has only methods (which can have a “symbolic” name). The usual precedence rules are based on that name.

- case classes: I love them.

- _: The underscore has one meaning, “there is something, but I don't care about the name”. Super simple.

- forgetting = in a function def can make it mean something else: I agree, it is very error-prone. As far as I know, there are some proposals to get completely rid of procedure syntax.

- currying syntax: PinS has a pretty good explanation why it works that way. It is certainly not perfect, but less error-prone than alternatives.

- the imports (especially renaming): Many languages have this feature and I have not seen any issues with it.

- arbitrary rules on whether construction needs "new" or not: No. The rule is that you always need new to construct an instance.

-[3]: You can do crazy stuff in every language. Have a look at functional code written in Java.

- And it even has macros, but all of its very many language features aren't implemented as macros: No. In a sense, ALL features are implemented via macros, because the compiler API and the reflection API (macros) are pretty much the same underneath.


- I don't mind unifying operators and functions/methods, I think it's a great idea. What I do dislike is having lots of optional syntax that is however still used much of the time. I much prefer using ( ) only for disambiguation

- case classes are great because they're a Algebraic Data Types. I dislike their syntax

- the underscore is sometimes necessary for disambiguation, that's the only thing that bothers me

- I don't mind the fact that renaming imports is possible, I think that's great. I just dislike the particularly unusual syntax, since = is already there for symbol binding

- since there isn't a de-sugared version of every language construct, I doubt macros are indeed that equivalent. Again, I think macros are great, but it worries me when a language's syntax is already so complex through "hard-coded" methods (as opposed to the more programmatic macros)


Scala = scalable language. This is for all the reasons you said. Because the language allows so much, library designers can really extend the language itself and create whole new paradigms or do other powerful things you just can't do in any other language that's this stable and portable.


I started using Scala ~2.5 years ago for my undergrad thesis. At the time I didn't really know what I was doing and essentially wrote Java with map/reduce on collections.

I've been working steadily in Scala since and currently do so professionally. I'm a fan, especially with the Akka actor framework.

Lately I've been playing with Play, Akka and ReactiveMongo. For-comprehensions offer a terrific abstraction for dealing with asynchronous code. My current side project is "Street View for Flights" implemented in the above stack. Lots of calls to third-party REST APIs after checking if data has already been retrieved and inserted into Mongo. Code like the following allows for controllers to be asynchronous while staying readable:

  def byCode(airlineCode: String) = Action {
    Async {
      for {
        airline <- Airline.findByICAO(airlineCode)  // returns Future[Option[Airline]]
      } yield airline map { a => 
        views.html.airline(a)
      } getOrElse NotFound
    }
  }

The advantage for me is that those futures could be redeemed either by finding the requested object in Mongo and on failure retrieving it from a third-party API while not blocking and keeping the code readable. Either way, the controller just gets a Future without blocking.

Other parts of this project make heavy use of Akka actors to feed server-sent events (sort of a compromise between Comet and WebSockets). Development has been great fun because Scala really allows me to write code at a higher level. Asynchronous, typesafe, nullsafe code with the compiler as my safety net.


The main problem I have with actors is that they are untyped.

What's the point of having a powerful type system like Scala's and then throw it out of the window just so I can use a distributed framework?


Scalaz has some nice (usefully typed) concurrency tools:

https://github.com/scalaz/scalaz/tree/scalaz-seven/concurren...

https://github.com/scalaz/scalaz-stream

Like everything with Scalaz, the tools are great but almost completely undocumented.


> Like everything with Scalaz, the tools are great but almost completely undocumented.

Exactly. I will start considering scalaz once its authors grow up and realize that the lack of documentation is not a sign of quality.


The maintainer and contributors have full-time jobs. On the one hand, part of that job is keeping up Scalaz for their own professional usage. On the other hand, no part of that job is documenting it for everyone else.

They could just have kept the code proprietary.


Really now? As if these guys get paid to do create and fix scalaz all day right? Like Oracle yeah? This is the story about every single open source project. You can choose something else, wait it out for documentation, or contribute it. Lucky you even have the source!


My understanding is that the new typed channels feature in the upcoming Akka 2.2 release will address this.

The macro feature introduced in Scala 2.10 makes this possible.

http://doc.akka.io/docs/akka/2.2.0-RC1/scala/typed-channels....


It's possible to make them typed with the stdlib[1]. Link also gives some reasons as to why they're untyped. Short answer is it started as a way to replicate Erlang in Scala[2].

[1] http://stackoverflow.com/questions/5547947/why-are-messages-...

[2] http://article.gmane.org/gmane.comp.lang.scala/12988


let's say you have more than one future:

    findAirline:        AirlineCode =>                Future[Option[Airline]]
    getFlightsForToday: Airline =>                    Future[Seq[Flight]]
    findAvailable:      Seq[Flight] => Constraints => Future[Option[Flight]
compose them so that I get:

    findFlight: AirlineCode => Constraints => Future[Flight]
I don't want `Future[Option[Flight]]` since Future has own error handling (using Try). No cheating by using scalaz monad transformer.


    def getOrThrow[T](x: Option[T]): T = x.getOrElse(throw new AirlineError)

    def findFlight(code: AirlineCode, constraints: Constraints) = for {
      airline <- findAirline(code).map(getOrThrow)
      flights <- getFlightsForToday(airline)
      available <- findAvailable(flights, constraints).map(getOrThrow)
    } yield (available)
No idea why you consider using scalaz to be cheating.


ah, getOrThrow! nice.


I'll readily admit that my Scala isn't 100% idiomatic, I'm still learning!


From my point of view and understanding, for is not good for this. Isn't it blocking? Say you have

  for 
     a <- forA
     b <- forB
     c <- forC(a)
it does not do a and b in parallel and then c, or does it?


It depends. Let's imagine forA, and forB are expressions that evaluate to futures of Ints. This runs them in serial:

   for {
     a <- forA
     b <- forB
   } yield a + b
This runs them in parallel:

   val fa: Future[Int] = forA
   val fb: Future[Int] = forB

   for {
     a <- fa
     b <- fb
   } yield a + b
(I dropped forC from your example as it has a dependency on the result for forA, and thus can't run in parallel.)


That forC has a dependency on a was the intention, so it needs to be run in serial.

I can't see the difference between your examples and so am confused why 1.) is serial 2.) is parallel.


At the risk of being trite, it's down to the order of evaluation.

You know that a for comprehension expands into calls to flatMap and map? So

  for {
     a <- forA
     b <- forB
   } yield a + b
expands to

  forA flatMap { a => forB map { b => a + b } }
Remember that forB creates and returns a future. Only when this future has been created will it start running.

It should be apparent that forB is not evaluated till forA's future delivers a value, and thus the future returned by forB will run in serial with the future returned by forA.

In the other example the futures are created outside of the for comprehension, and thus start running in parallel.


Ah ok, thanks!


Actors and the way Scala handles async is one of the reasons I wanted to get into using Scala on Android actually. The awkward way Android handles it is chock full of Java boilerplate and Scala's way is just much more elegant.

Another feature that got my attention was the ability to have a SQL framework that handled things similar to LINQ. I haven't tried it much yet, but Squeryl[1] has looked promising for being a Scala equivalent. I may have to look into Akka more though as that will easily take care of async SQLite calls as well[2].

[1] http://squeryl.org/introduction.html

[2] http://www.gamlor.info/wordpress/2012/05/async-sql-and-akka/


I used Squeryl in my thesis (admittedly a while ago) and Slick[1] on a more recent project. Like you, I had ample experience in LINQ and it's definitely the feature I missed most from C#. I'm a fan of Slick.

I'm also looking forward to async SQL calls.

I've been building some Akka-based projects for a client and both they and I have been thrilled with the results. They're a startup that's gaining traction and they brought me in to help with scalability. I won't go so far as to say that Akka is a magic bullet but it makes reasoning about scalability far easier, though in our case we're mostly dancing around the IO bottleneck.

[1] http://slick.typesafe.com/


My GSOC project for this year is an extension to for comprehensions to enable LINQ-like conciseness without LINQ's inflexibility. If it ends up being merged into the compiler proper (a pretty big if), it should really help to make writing complex queries a lot less painful.


That's excellent. 9 of 14 proposed projects were accepted

http://www.scala-lang.org/gsoc2013

http://www.google-melange.com/gsoc/projects/list/google/gsoc... (type "scala team" in "Organization" box


Squeryl doesn't allow you to drop down to raw SQL, so I'd suggest avoiding it.


It is also rather broken, and the author doesn't appear to care. I'd second the suggestion to avoid it.


That's a shame, on both accounts. It looks nice and the right way to abstract out SQL, but admittedly, I would not use it if it won't let you drop down to SQL for something that needs it.


Starting adopting Scala about 18 months ago after much frustration with Java's copious boilerplate. It's like a breath of fresh air and feels in many ways like a dynamic language thanks to type inference. We still use many Java libraries but interfacing with Scala is a breeze. It's got more up-take than Kotlin or Ceylon and I'd say the only decent alternative on the JVM is Clojure but that's a different beast. If you're in a position where your after functional programming on the JVM then consider not waiting years for Java to catch up. Give Scala a go.


Same experience here.


What I dont like about scala is its "syntaxtic flexibility". Or how I would call it, non consistent syntax.

Too much features: Scala has everything, it seems like the language designers coudn't make a choice about what is best. "Whoo this is cool, lets add it". One word: implicits, arrgh

Also the fact that is built on top of java... When you design a good language, you should try to do it right, and leave all other out. However this is a design choice of Scala. And I think this choice makes the language a short term language, just as a stepping stone for java programmers to better languages.

- end of rant -


Personally, I think implicits are one of the most useful, influential and practical features for extensibility and code reuse. They allow flexibility and extensibility without too much typing, while keeping things clean and safe (type-checked).

Imagine, for example, math. Sometimes, I want 1/3 to be exact (i.e. a rational), so that 1/3 * 3 == 1, other times I want 1/3 be a float (eg. when doing numeric algebra). In a language with implicits, I could simply import the correct math object that provides the correct implementation of /, and use it in the whole module. Furthermore, if this math implementation is passed as an implicit parameter, every other library/function I use (even in another module) automatically uses the implementation of / that I want.

This could be used in many other situations as well, such as memory management, where we could have an implicit policy (allocate on stack, heap, reference-counting, GC, ...), "opening" of classes (import a class and an implicit extension of it), and many other.

In a way, this is similar to what Haskell type-classes do, except that it can actually be controlled by the programmer.


Implicit Conversion is indeed powerfull. But so is the goto statement. My experience with implicit conversion is: "Lets read this code, Ah i think it does X. Let's run it, wait what is happening, ow my why is this implicits here?"

You could argue that you should use them with care, but i'd argue not to include them in the language. You'll go c++ all the way.

Implicits are very powerfull for creating DSL's in Scala. And indeed scala is a good language for doing DSL's. But for me understanding what was happening by reading code was difficult. And i think code should be easy to understand.


The difference between goto and implicits is that the former are completely statically safe - typechecked and declared, and an IDE can at any point of the program tell you what's being passed implicitly. They are a bit like local (i.e. funcion-scope only) goto, which isn't that bad (and sometimes necessary, e.g. `break <label>`).


Too much features: Scala has everything, it seems like the language designers coudn't make a choice about what is best. "Whoo this is cool, lets add it". One word: implicits, arrgh

You mean implicit conversions, right? Because implicit parameters are the single best thing since sliced bread.


Yes, thanks for correcting me. Implicits parameters are not so bad, but still i'd rather love code to be explicit.


Bah, if they were explicit, they wouldn't be nearly as useful for parametric polymorphism.


Why don't you like implicits? Even the more conservative language C# has them.

It beats the heck out of having to do the following in Java:

BigInteger x = new BigInteger(someBigNumString);

BigInteger sum = x.add(new BigInteger("1000");

When you can do this in Scala (or similar in C#):

BigInt x = BigInt(someBigNumString)

BigInt sum = x + 1000

If you're going to say it can be abused, lots of things can be abused in any language. I prefer sanity in this case for implicits over risk of abuse. Having to use something like BigInteger in Java without implicits just makes my head hurt trying to read and write code using it.


I've done exactly one project in Scala, so I'm by no means a Scala expert. My objection to the implicit conversions is mostly when they're used with DSLs. Our project used several libraries that each implemented their own DSLs that of course made use of implicit conversions.

There were two things struck me as questionable about the extensive DSL support in Scala. First, Scala source files that used one library's DSL ended up looking like they were written in a different language than Scala source files using another library's DSL. That, to me at least, makes it harder to read the source quickly and understand whats going on. This wasn't a horrible problem, but I found it somewhat burdensome to reorient myself when switching between DSLs, so I feel like it's an overall negative feature of the language. Sort of the opposite of the benefit that more consistant looking languages like Python and Go provide.

It also means, at least for me, that and IDE is necessary in order to understand what's going on in source files using certain DSLs. I'm an Emacs user and this is the first time I've felt like I really should have been using an IDE, which was irritating.

My second objection was that because of ambiguities between implicit conversions in different DSLs, source files that used more than one DSL had to fall back on explicit conversions and therefore not really use the DSLs. That made some source files using a given library look very different from other source files using the same library, since one was written using the DSL and the other wasn't.

This is really my major objection to the language. In many other ways I really enjoyed Scala and wish I could use it more. Yet I wish DSLs and implicit conversions were used much more sparingly in Scala libraries.


Could you expand on what exactly you feel is syntactically inconsistent?

Considering features: Well, it certainly depends where you come from. If you come from Scheme, Scala is huge. But if you come from Java or C# or F# or ..., Scala is refreshingly small, consistent and self-contained.

Regarding implicits: Most languages have implicits, they are just hard-coded into the language and will be there forever. In Scala, you can just de-import the ones you dislike and if enough people dislike those, they might even get deprecated and removed.

Implicits seem to be really the feature all people except actual Scala users love hating, especially exactly those kinds of implicits which aren't even widely used anyway. Implicit conversions make up maybe 10% of all usages of “implicit ” and require a feature import.


Syntax: If there are 3 ways to do the same thing, you remove 1 to have a more consistent syntax. See the point in the article of the author.

Features: Compared to Java, scala has a lot more features. It has functional programming for example, but its not done right, due to it's java bases. For example, try currying, you need extra syntax to curry functions.

Implicits: They might have a place, but see my comment above this one.


Syntax:

The author in the article is complaining about 18 different ways to define a function. Of those 18, the ones which use postfix operators create a feature warning already and will stop being accepted without the appropriate flag in the future.

If you eliminate the ones which use additional but pointless curly braces (Really, what's the point? Why not add 5 curly braces instead of 1?), you are pretty much left with either a named variation (n =>) and an anonymous variation (_). That seems pretty reasonable.

Features:

Compared to Java, Scala also removes a lot of stuff. Having read both language specs, I say Scala comes out as a winner, because the actual features it has are actually working and don't consist of tons of pointless cruft like in Java or C#.

Implicits:

Really, implicits seem to be a big deal for those people not using Scala. For actual users of Scala, they are not. I have never touched a codebase where implicit conversions posed such an issue as it is claimed in blogs. In practice, implicit conversions are pretty rare and mostly used for Java compatibility. The good thing is that you can get rid of the ones you don't like in Scala, which you cannot do in pretty much all other languages (where they are built into the language itself).


Best line in the article

""" If a grand unified theory of programming language existed, its implementation would be called Scala """


I think Kotlin would be a better candidate for this. Scala's surface area is way too big for this purpose.


Kotlin is a promising language, but still pretty new, so it doesn't have as many libraries out there tailored for it yet or questions asked about weird corner cases you might encounter (so it can make it a bit harder to track down bugs). That has its positives if you want to be a pioneer in the language and start popping out some useful open source libraries though.

I love what Jetbrains does though and actively read their blog as they keep improving it. Kotlin has a bright future (I think some of the developers of Groovy are working with Jetbrains on it), but still a language in its infancy.


Scala may be a safer solution because Kotlin is newer, but that doesn't stop Kotlin being a better choice than other older languages like Groovy.

Today the Groovy P.M. announced they're adding statically-typed traits (http://groovy.329449.n5.nabble.com/Adding-Trait-to-Groovy-td...) to Groovy, talking about them like they're an innovation. But they were already implemented by former Groovy++ developer Alex Tkachman (https://code.google.com/p/groovypptest/wiki/Traits) 2 years ago. Groovy added static compilation into Groovy 1 year ago by copying it from Tkachman's Groovy++ codebase, then announced it to the world as "Groovy 2.0" without crediting him. Now they're trying the same trick again, laundering the Groovy++ Traits and passing it all off as "Groovy 2.2".

Alex Tkachman is now one of the Kotlin developers (along with Groovy's creator James Strachan). So which codebase would you trust: one laundered without credit from someone else's implementation (Groovy), or a second try from the actual person who wrote the first attempt (Kotlin)?


Kotlin looks(ed) promising. When I tried Kotlin some time ago they mixed plans, wishes and facts in the "documentation" which made it very hard to do some work, as many "features" in "examples" had not been implemented (And I thought to myself how stupid could I be to not get the examples working)


Yes the official documentation is indeed out of date. I am working to fill the gap (http://goo.gl/TkgqR - in progress)

The potential growth for Kotlin usage will be on Android platform especially after the new Android Studio is based on IntelliJ 13. Kotlin fits nicely here and it's a relatively small language.

Scala though is quite a pioneering language on the JVM. I think a lot of Kotlin features and design are influenced by Scala.


If you like Kotlin also look at Ceylon from RedHat. In some ways very similar to Kotlin with null-safety and improved generics.


Actually Kotlin has null safety as well[1]. Not sure how generics in Kotlin compare to Ceylon, but it also improved on Java's generic support[2] by eliminating wildcards, type projection, inferred types and some other features.

Random question, but how far along is Ceylon's development compared to Kotlin's? I know they're both relatively new still, but just wondering how feature complete it is so far.

[1] http://confluence.jetbrains.com/display/Kotlin/Null-safety

[2] http://confluence.jetbrains.com/display/Kotlin/Generics


See here: http://ceylon-lang.org/documentation/1.0/roadmap/

I hate to say it because I like JetBrains and have given them lots of money over the years but I prefer Ceylon to Kotlin. They are very similar languages but I just like the Ceylon syntax more.


I started using Scala last year with the Play! 2 framework (did a write up on it earlier this year on HN) and was a breathe of fresh air. I didn't have any prior functional programming skills so it was a bit of learning functional programming and the language as well, but it was a fun experience. When ever I have the chance to choose the tech stack for a new project whether personal or professionally, Scala and Play! is the first choice. I just finished a Scala lib for rethinkdb (will announce later).


Description of apply() is backwards or at least unclear; it's not that "new Song(name) goes to Song.apply(name)", rather, "Song(name)" -> "Song.apply(name)", which is commonly (and automatically, in the case of case classes) implemented as "new Song(name)".

It's worth mentioning the positive side of more concise syntax for closures - as someone who previously used lamdbas heavily in python this is a real win. "Seq("1", "2", "foo").map({n => stoi(n)})" should just be "Seq("1", "2", "foo").map({stoi(_)})" - or, in this particular case, "Seq("1", "2", "foo").map(stoi)". Of course, the price is shown at the end as having more than one way to write the same thing - but the differences in those examples are (IMO) superficial and don't impair readability.

The specific problem of infix/suffix methods should be solved with 2.10's compiler flags. They should also go some way towards improving source compatibility (features for which the syntax is expected to possibly change will stay behind flags), while 2.10 introduces a better binary compatibility policy. Still, most of the criticism is fair, and I'm pleased to see a comprehensive impression post like this.


I started out with Scala three years ago on a hobby project when I wanted an impure functional language compatible with a Java library I felt myself bound to use.

Since then, it has become such a strong favorite that I have remodeled part of my own hobby programming language based on Scala.


There seem to be some problems in the examples.

  scala> def theSquareMullet(i:Int) = i * i
  theSquareMullet: (i: Int)Int
  
  scala> def theHoffSquareMullet({ mullet: => Int }) = mullet * mullet
  <console>:1: error: identifier expected but '{' found.
       def theHoffSquareMullet({ mullet: => Int }) = mullet * mullet
                               ^
  
  scala> def theHoffSquareMullet(mullet: => Int) = mullet * mullet
  theHoffSquareMullet: (mullet: => Int)Int
  
  scala> theSquareMullet(theHoffSquareMullet(10))
  res0: Int = 10000


Completely new to Scala but I think that "18 ways" code sample is a bit exaggerated. It is just a choice between C#-ish "a => a + 1" and Haskell-ish "_ + 1".


Like the author, I've been using Scala more and more as of late (mostly after finding it to be a viable alternative to Java on Android). Perhaps the biggest thing that I've had to get over is the "feature freedom" of the language after being walled in by Java on Android. I know I'm not too far off in saying it, but it's like Martin Odersky created it in direct response to the nanny-like restrictiveness that Java has, but perhaps went too far in some areas (as the article describes a bit). He did write the current java compiler, so he's well familiar with how Java is. I just sometimes get the feeling someone pressed accept to every feature enhancement to the language at some point as just about any feature you can think of in a modern language has found its way into Scala. Generally, I find that to be a good thing, but I can see how it would be off-putting to some and makes Scala somewhat of a controversial language for both imperative and functional language advocates.

If one is not careful and adhering to a formal style guide, it would easy to end up with an unreadable mess of inconsistent code. Anyone with some grounding in programming already at a professional level shouldn't have a problem, but someone that's relatively new to development might want to look into another language. For example, all of these are valid ways to create a class with some parameters/properties:

https://gist.github.com/yareally/5811498

After having to use Java on Android for the past three years, such freedom is both liberating and shocking at the same time. I use C#, JavaScript and Python pretty frequent as well, but it's just I'd say Scala is even more liberal than any of those feature wise. It's more like Perl (not quite, but close), but not quite in the area of a Lisp variant. Scala is definitely written from the viewpoint of the developer and not the intended users though. It's also nice to have access to features that are standard in languages like Python, Ruby, C# and functional languages. Seeing 13 lines of Java become 1 line of Scala[1] is a great feeling.

I'd say if you have experience with Java, C#, Python, Ruby or any functional language you'll pick up on Scala pretty quick. If Java is your only language experience, it might be a bit rough at first, because of the expressiveness and freedom of the language, but don't let it detour you. If needed, you can mostly stick to the imperative side of Scala and slowly work in more functional features as well as some of the useful syntactical sugar stuff (like operator overloading) that Scala provides.

[1] https://gist.github.com/yareally/5810767


> If needed, you can mostly stick to the imperative side of Scala and slowly work in more functional features as well as some of the useful syntactical sugar stuff (like operator overloading) that Scala provides

I'd say that's a bad idea.

People keep saying that Scala is not an opinionated language and that you have to make choices and stuff. That's not true and in fact, Scala is a very opinionated language that makes imperative code painful. That's why some beginners get so frustrated when they pick it up. Because they come with certain wrong assumptions about how features in Scala work.

Examples: Scala does not have "break" or "continue", while "return" does not behave as many people think it behaves. The "yield" keyword in "for" expressions is also totally different than the "yield" in C# or Python or Ruby. Actually "for" expressions in themselves are actually monad comprehensions - powerful, elegant, but definitely not your grandma's foreach. Also, collections are immutable by default.


You have a point in that the features may not be one to one equivalents, though that's generally the case when using any new language to a point. Even Java to C# vary a bit for their overlapping keywords/features. Yield might return a collection in Scala instead of an iterator like in Python, but that's not a huge knowledge leap to wrap one's head around.

Are collections immutable by default in Scala? I thought each each was treated as a separate, but equal package (scala.collection.mutable and scala.collection.immutable) and collections within scala.collection itself can be either mutable or immutable since they're super-classes to both subpackages. The difference between the super-package collections and the subpackage collections.immutable being that collections.immutable was guaranteed to be immutable.

I've kind of avoided "yield" so far and opted for the functional equivalents. Something like

val result: Array[Int] = for (elem ← n if n % 2 == 0) yield 5 * elem

just looks more readable as:

val result = n.filter(_ % 2 == 0).map(5 * _)

or in more functional syntax:

val result = n filter { _ % 2 == 0 } map { 5 * _ }

I don't think imperative code is necessarily painful in Scala, it's just constructed a bit differently. On the other side of the paradigm, functional language advocates seem to say functional programming in it is also painful[1]. Just seems Scala cannot 100% please everyone 100% of the time.

[1] https://groups.google.com/d/msg/scala-functional/kvbaE6cAzqM...


Btw, regarding for-comprehensions and Futures, there's a new project that's going to make things interesting for working with Futures: https://github.com/scala/async

> On the other side of the paradigm, functional language advocates seem to say functional programming in it is also painful[1]

Worth pointing out that the people advocating for a better language in that thread, including the one that started it, have problems with Haskell too (currently the poster child for functional programming). It is the reason why many of them are using Scala, whether they like to admit it or not. In that thread it is even argued that lambda-calculus itself is outdated because it is inherently sequential.

Scala attracted many idealists that aren't pleased with any mainstream language. On one hand it is good, because it moves the language forward. By comparison the Go community is kind of toxic. On the other hand, people that don't get the context of that discussion jump to conclusions.


After going back and rereading some of the posts, I agree without you about it having a group of angry programmers that aren't happy no matter what they get.

That project looks interesting though. Looks like it's almost based on the new async abilities in C# 5.0[1]. Have you tried it any yet in Scala?

[1] http://fizzylogic.nl/2012/05/04/adding-asyncawait-support-to...


Why do you say the Go community is toxic?


I for one think that the for comprehension syntax is more readable, especially when you start iterating over multiple sets.


> Actually "for" expressions in themselves are actually monad comprehensions - powerful, elegant, but definitely not your grandma's foreach. Also, collections are immutable by default.

This definitely threw me for a loop when I started using Scala. I banged my head against the keyboard a few times trying to get for comprehensions to do what I thought they should do.

Once I began to fully understand the relationship between for comprehensions and monadic operations, especially on Futures and Options, I began to understand their power.


> I just sometimes get the feeling someone pressed accept to every feature enhancement to the language at some point as just about any feature you can think of in a modern language has found its way into Scala.

That was also my impression. Clojure is sometimes painfully restrictive (I need forward declarations for functions if I use them before they are defined? In a compiled language in 2013? Really?), but at least it is curated.


With all due respect, this impression is just folklore.

The difference between Scala and Clojure is the difference between ML and Lisp. Languages from the ML family are statically typed by definition, therefore they need slightly more features to be expressive. On the other hand, the trade-off is worth it for many people, because the compiler actually helps you - for example it's far easier to work with various functors (such as monads) in ML languages, than it is to do that in Lisp.

Also, Clojure is not "painfully restrictive" or "curated". Name one thing that Clojure doesn't allow you to do.


Clojure does not allow you to define reader macros. Though I do not claim that Clojure is “painfully restrictive” because of this.

I would like reader macros because they would enable the implementation of sweet-expressions (http://readable.sourceforge.net/).



Clojure has always intrigued me, but I've stuck with Scala so far so I don't scare any of the more Java inclined developers I work with when they read my code.

I keep thinking with Scala though, I'm going to run into some really awful looking code one day from someone overly abusing all of its features. I know know even the most restrictive languages can be abused, but it just feels like Scala leaves the window much more open for that.


> I keep thinking with Scala though, I'm going to run into some really awful looking code one day from someone overly abusing all of its feature

I also keep thinking that, but it never really seems to happen in my experience.


I'd be interested in hearing more about what you find restrictive besides forward declarations, which I've never found to be a big deal. As a side note, there was a pretty interesting discussion on HN between Steve Yegge and Rich Hickey about that: https://news.ycombinator.com/item?id=2467359


Do you have any links to suggested style guides?

Google returns this: http://docs.scala-lang.org/style/ or this: http://davetron5000.github.io/scala-style/index.html but do you have any that you'd recommend?



I mostly follow the official one on Scala. I deviate from it a little to help me stay sane when switching between languages like 4 spaces tabbing and sticking to K&R style[1] for indentation/braces. Using an IDE like Intellij or Eclipse can also help reinforce consistency as well since you can set the way it formats for you (and also have it auto-format before you commit to git).

Most important thing is to just stay consistent with whatever you decide upon more than which formal style you choose. If I were working in a team with Scala, then I would stick with a formal spec (or just let the IDE auto-format for me to adhere to the team's style when committing).

[1] http://en.wikipedia.org/wiki/Indent_style#K.26R_style


> If one is not careful and adhering to a formal style guide, it would easy to end up with an unreadable mess of inconsistent code.

This reminds me a lot of C++: powerful but unless you agree on a consistent style and only using a subset of its functionalities, you end up with nightmare code bases.


With great power comes great responsibility.


enjoyed the article very much! nice analysis.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: