

A farewell note to a programming language - fogus
http://matthiasnehlsen.com/blog/2014/12/04/Farewell-Scala/

======
noelwelsh
On Monday I'm giving a talk at Scala Exchange on my take on idiomatic Scala.
For those of you who can't make it, I'll give a quick rundown. You basically
need four patterns:

\- algebraic data types

\- structural recursion

\- fold, map, and flatMap

\- type classes

That, in my experience, will cover the majority of code you need to write in
Scala and give a solid basis for a robust and comprehendible code base.

It's unfortunate that in Scala algebraic data types and type classes require a
bit more code than in most other functional languages.

E.g.

    
    
       sealed trait Foo
       final case class Bar(...) extends Foo
       final case class Baz(...) extends Foo
    

vs something like

    
    
       data Foo = Bar ... | Baz ...
    

for an algebraic data type, but it's really not so onerous to type.

These patterns are really truly shockingly simple to use. We teach them in
introductory courses and the majority of people get them.

It's true that Scala has some warts, but as software engineers we ought to
make decisions based not on our personal biases but on a consideration of the
problem domain and tradeoffs involved. If you want 1) static typing, 2) a
modern language, and 3) JVM compatibility then Scala is the best choice at the
moment IMO. Remove one of those restrictions and other choices come into the
picture.

Update: If you're interested in learning more about these patterns, on Friday
we're going to send a free excerpt of our "Essential Scala" book to our
mailing list. The excerpt will include material on algebraic data types and
structural recursion. You can sign up here:
[http://underscore.io/newsletter.html](http://underscore.io/newsletter.html)

~~~
lomnakkus
I think you just described Haskell in your four bullet points (which I'm sure
you know, or at least know of.) Of course it comes with the baggage of
pervasive laziness, so there's that potential objection...

It can't run on the JVM, but to be honest, I've never actually observed in
practice what's so great about the JVM (if you're running functional code).
Everyone I hear claims that the JVM is great (left & right), but I just don't
see it. Maybe I'm just ignorant.

~~~
noelwelsh
The true benefit of the JVM is the ecosystem. There is a load of ancillary
stuff like database drivers and web frameworks, to more exotic stuff like
rendering PDFs, that every application needs. It doesn't add value to work on
this stuff yourself but you can just about guarantee there will be on the
library on the JVM that does what you want. It might not be pretty but it will
exist somewhere.

This is particularly the case in the big data space, where all the major
frameworks are run on the JVM.

For many people, interfacing with legacy Java code is also important.

And yes, I advocate using Scala much like Haskell.

(There is also the performance of the JVM, which is pretty good, but this is
only a point worth mentioning when comparing to languages like Ruby and
Python. Most functional languages have good compilers and runtimes.)

~~~
lomnakkus
Honestly, the IME the JVM ecosystem isn't _that_ great. I think you could
probably find a bigger/better ecosystem for C/C++ at this point in time. (Even
going as far as Big Data or PDF support, but I know nothing of the former.) I
recognize that the JVM has (for several years at least) been sold on this
premise, but I just don't think it's true, or at least not true to the extent
that the PR says.

Don't get me wrong... it's _good_ but _not_ great (in my conception of
things). Even if you find some indispensable JVM-based library, then why not
just shell out to an executable jar (or whatever) that does what you need? At
least you'll avoid classpath-hell that way.

~~~
noelwelsh
Maybe, maybe not, but I had three criteria and C/C++ certainly don't meet the
other two. (There are other criteria we use when making these kinds of
decisions, like performance, speed of development, availability of developers
etc, but I thought we were talking about modern functional languages so I
didn't bring these up.)

I think the language that hasn't the biggest chance of upsetting the JVM is
Rust. Mozilla talk about Rust as a C/C++ replacement, but I actually expect
they'll see more interest from JVM focused developers. A lot of current
systems programming uses the JVM (all the aforementioned big data systems like
Kafka, Cassanda, HBase, etc.) A number of these systems have issues with the
JVM, particularly GC performance on large heaps, and Rust would be very
attractive here. Scala developers in particular are used to modern language
idioms and so could relatively easily switch to Rust.

~~~
lomnakkus
> (There are other criteria we use when making these kinds of decisions, like
> performance, speed of development, availability of developers etc, but I
> thought we were talking about modern functional languages so I didn't bring
> these up.)

Oh, indeed -- and I might even agree on the non-platform arguments. And I'm
not discounting those -- I'm just saying that the JVM (not
Java/Scala/Groovy/whatever) argument is overstated :). IMO, as always.

Agreed about Rust as well, I think. Java programmers are already used to the
verbosity (tongue firmly in cheek ;)).

EDIT: Actually, come to think of it... many of the criteria you mentioned
would apply to JavaScript developers, wouldn't they?

------
saosebastiao
Interesting. I've followed Matthias' project as I've tried learning the Play
framework as well as front end development, and it has been incredibly useful.
Incidentally, I learned Scala after I knew Clojure reasonably well, and I feel
like I could apply the same arguments in the reverse direction.

When it comes to the back end, I'll likely choose Scala 100% of the time. I
really believe there is no substitute for a strongly typed ML-derivative for
that type of environment. Additionally, there are a strong set of robust scala
libraries (Typesafe mostly) that are completely production ready, and java
interop is much more natural when you need it.

For the front end, I'm currently using Javascript, but I have toyed with the
idea of both Scala.js and Clojurescript. This is where Clojure really makes me
mad. I feel as though the dynamically typed Clojurescript should be a better
fit as a compile-to-javascript language, but in every instance I've tried,
Scala.js just works better. It compiles correctly, error messages make sense,
much better documented, and there are fewer deviations from the core language.
And the clojurescript libraries are mostly terrible in this regard...even the
super-hyped ones like Om. My biggest pet peeve are the tutorials that force
you to learn unrelated things (like Datomic, Emacs, Ring, etc) to be able to
walk through them. I really feel like Clojurescript had a chance to shine
here, but I find it far less inspiring than the relatively immature Scala.js.
Oh well.

------
tel
If you like Scala but find it too scattered then there's always Haskell* :)

(*) Not that there aren't a thousand reasons to not choose Haskell. This is
merely obligatory temptation dangling.

~~~
slm_HN
It's official. Haskell has become the Beowulf cluster of Hacker News.

~~~
codygman
Beowulf cluster?

~~~
jimm
It's an old-school Slashdot meme: "a Beowulf cluster of X", where X =
commodity hardware, microprocessor, or Furby.

------
speedkills
I found your experience closely mirrors mine with scala. At my current shop we
write mostly ruby and scala. The ruby code between developers looks much more
uniform than the scala code I believe due to the fact that while trying to
please everyone scala hasn't yet developed much of "the scala way". I do hope
this changes as I really enjoy scala. Currently my team is experimenting with
style/punting tools like stylecop to try to bring a little consistency to our
code. Too early to say how it will work out but I would love to hear from
others how you try to bring a team style to a code base that will happily let
a fully functional developer, a fully object oriented developer, a straight
imperative developer, and someone who believes in mixing these things all work
side by side. Mentally by giving up the possibility of nothing you have to
learn everything which means loading a lot of the scala compiler up into your
brain before even trying to read a bit of anyone else's code.

~~~
lostcolony
Mixing an imperative developer with a functional developer? That's asking for
trouble. You'll have to be converting between mutable and immutable data
structures anywhere the two interact. Or forcing the imperative developer to
be largely functional due to the immutable data structures everywhere that
prevent him from using imperative approaches. Or forcing the functional
developer to write in a largely imperative style due to the mutable data
structures that prevent copying from being efficient, and can be mutated any
time they pass out of his/her code.

Or to put it another way; Scala as an idea may be fine; you can mix imperative
and functional together, by picking which data structure and approach for a
given problem is 'right'. But in a team environment? Touching someone else's
code in a particular paradigm means you have to be familiar with, and expect,
that paradigm. You can come up with a team that agrees on what paradigm
everything must be written in (and that can be anywhere on the continuum), but
you can't mix and match and expect developers to not have to learn every
paradigm in use.

~~~
tel
The ST monad would like a work with you :)

~~~
lostcolony
Which doesn't help the imperative programmer who is having to interact with
functional code.

And an ST monad makes no sense unless you're interacting with imperative code
(obviously, hence your bringing it up), which means you already understand
what imperative is, and are still having to convert your immutable structure
to a mutable one, for the imperative code to operate on, and to recognize it
will be modified in place; to use the ST monad the functional programmer
already has to understand imperative programming.

It also seems like it would fail to encapsulate the side effects an imperative
function may have, since that function is able to interact with state
elsewhere, that isn't actually encapsulated. I.e., the ST monad makes sense
when dropping into update-in-place for performance reasons, but when there are
side effects that are not ensconced within the monad (remember, the function
you're calling was written by an imperative programmer, in a language that
allows side effects outside of a monad; not Haskell), the ST monad does
nothing to make it functional, and oh crap, now your functional programmer has
the same problems as an imperative programmer, in having to figure out WTF
this function just changed in some other imperative chunk of code, in some
other process or object or whatever.

So given imperative and functional paradigms, even using the ST monad, if the
functional code is to call the imperative, and the imperative is to call the
functional, both the functional and the imperative developers have to
understand the other paradigm, -and- deal with the considerations of both.
You've upped the complexity of your system considerably.

~~~
tel
It doesn't allow free crossing between an (imperative + mutable) world and a
(value-centric + immutable) world, no. It, instead, allows for clear
boundaries to be set between the two and each to be embedded into the other.

The ST monad also does exactly restrict the scale of effect of mutability
which can occur. It's not a license for the imperative programmer to do
whatever they want---it's a license for them to solve problems in the way they
prefer within a particular ensconced region.

If you want, you can write a program where everything lives inside of a giant
ST monad layer. You always do this if you replace ST with IO, in fact. Each
bit which can be made purely functional will be embedded into this monad and,
for sake of sanity and testing, those functional bits ought to grow and grow.

But it doesn't really demean the IO/ST segment. An imperative programmer can
live happily there without much trouble at all.

~~~
lostcolony
"It doesn't allow free crossing between an (imperative + mutable) world and a
(value-centric + immutable) world, no. It, instead, allows for clear
boundaries to be set between the two and each to be embedded into the other."

I wasn't saying you couldn't set boundaries; you have them implicitly simply
by dint of the fact that in Scala, mutable/immutable is based on the type, and
the type system is enough to enforce that. But now you have a performance
penalty being introduced based on who works on a given part of the code, and
one that can easily compound.

"It's not a license for the imperative programmer to do whatever they want---
it's a license for them to solve problems in the way they prefer within a
particular ensconced region."

But for the imperative programmer to know what not to do he/she has to
understand functional coding, and choose to eschew certain techniques that
might be viewed as acceptable from a purely imperative perspective.

Please note, I didn't say you -can't- do it. Just that it's asking for
trouble, and that either you have to understand both paradigms or you suffer a
performance penalty (converting from mutable to immutable and vice versa). And
that if you ever want to touch someone else's code you have to be familiar
with the paradigm. Not proficient, but enough to realize what you have to do
to be able to interact with it properly/safely, that that requires a broader
depth of knowledge on the part of each team member than if you picked one
paradigm, and that leaving them to know only their paradigm will not work. The
imperative person has to figure out higher order functions, working with
immutable data structures, etc, to make use of some of the stuff the
functional guy has written, and the functional guy has to be comfortable with
destructive updates, side effects, etc, to be able to make use of what the
imperative guy has written. Yes, they both can interface with the other, but
what they have to know is much broader, and every time they interact you risk
bugs and performance penalties that you'd not have if you picked one paradigm
alone.

------
emcrazyone
I think the article is fundamentally flawed from this comment alone:

"In well over a year of working in Scala teams there hasn’t been a single day
where I felt that there was a shared mindset about how to develop a system or
even approach a problem."

So this guy expects a programming language to create a shared mindset?

I've been developing software for close to 17 years in more languages than you
can shake a stick at and none of them do this for you. It's always about
picking the right tool for the job and/or team.

A shared mindset comes from other planning type activities like use cases,
function/non-functional specifications, and general architecture type planning
before you write code. Especially for larger projects.

I think software patterns tend to help drive synergy in a team environment.
It's not perfect but my experience has shown me and the folks I work with at
least, that adopting patterns helps to bring us together but those patterns
are usually fleshed out during architecture planning activities.

~~~
cwyers
I think there's a huge contrast between a language like Perl, where There Is
More Than One Way To Do It, and say Python, where "There should be one -- and
preferably only one -- obvious way to do it."

~~~
RodgerTheGreat
"The Zen of Python" makes a number of lofty claims like that, but the actual
language design doesn't embody them well if at all. To pick an example off the
top of my head, there are three syntaxes for string literals (single quote,
double quote, triple quote) and three prefixes (raw, binary, unicode) which
can be combined in a number of ways. As a result python offers 15 ways(!) to
express a string literal.

~~~
pekk
That's really disingenuous. The "Zen of Python" is not bragging on the part of
Python, but an expression of values in a community.

~~~
TodPunk
His point is that those values don't exist in most of the community as
exemplified by their code and blogs, and this is largely because the language
encourages straying from those values.

I should note that I agree, and I'm a Python dev full time.

------
waps
A programmer complains that different programmers have different styles of
programming in Scala ...

and ... switches to a lisp. You know, languages that execute code by rewriting
the syntax tree of the running program ...

This ought to be good.

This is not meant to be disparaging against LISPs. I'm just alluding to the
fact that while there are 5-10 ways to do the same thing in Scala, all looking
very different, working subtly different, there's 5000 different ways to do
the same thing in LISPs.

~~~
lostcolony
Every list of best practices, for every LISP, agrees that macro use is
generally a "use rarely" thing. And Clojure seems to have developed idioms
around simplicity.

Scala, on the other hand, has wildly diverging sets of best practices. The
feature set is huge, attempting to appeal to pure functional programmers in
their academic ivory towers, and the grizzled Java developers who believe OOP
is the one true way, and everyone in between.

It's easy to -say- that there are 5000 ways to do the same thing in a LISP,
and only 5-10 ways to do the same thing in Scala (both statements being
hyperbolic, presumably; there are infinitely many ways of doing each, after
all), the meaningful variations you are likely to see in the wild are far, far
lower in Clojure than Scala. And will likely be based on different
understandings/expressions of the problem, rather than on different language
subsets that the author prefers.

~~~
lispm
> Every list of best practices, for every LISP, agrees that macro use is
> generally a "use rarely" thing.

Not really. This best practice is for beginners and mid-level programmers.
They either write macros for the wrong purpose or in problematic ways. Thus
they should avoid macros. Still they need to use macros, since languages like
Common Lisp provide a lot of functionality through macros.

To get past that stage a book like 'On Lisp' by Paul Graham helps.

Many, but not all, advanced programmers will use and write a lot of macros.

~~~
nickik
Thats just not true in clojure. Good librarys in clojure have a data
interface, function to produce that data and maybe a thin macro layer to make
it a little more easy to use.

While 'On Lisp' is a cool book, I rarly find the really advanced macro stuff
usful. Once in awhile, you want to have something like a really good pattern
matching compiler, and then your macros come in handy. But day to day, you
dont need them much.

~~~
lispm
Let's look at some Common Lisp example:

[https://github.com/Wukix/LambdaLite/blob/master/lambdalite.l...](https://github.com/Wukix/LambdaLite/blob/master/lambdalite.lisp)

This is a recent tiny in-core database.

The code is using LOTS of macros. It also implements a few non-trivial macros.
Half of the code is implemented as macros.

Code like that is not unusual in Lisp.

------
swah
His Clojure implementation is here:
[https://github.com/matthiasn/BirdWatch/tree/master/Clojure-W...](https://github.com/matthiasn/BirdWatch/tree/master/Clojure-
Websockets)

------
swah
fogus, what should I read nowadays? BOOKS???

[http://blog.fogus.me/2011/03/27/the-long-lost-art-of-
thought...](http://blog.fogus.me/2011/03/27/the-long-lost-art-of-
thoughtfulness-in-blogging/)

~~~
swah
Ok found the answer [http://michaelrbernste.in/2014/10/21/should-i-read-
papers.ht...](http://michaelrbernste.in/2014/10/21/should-i-read-papers.html)

------
serve_yay
Well, OK.

------
covi
There are three and only three vague points conveyed in the article: (1) Scala
has "immense" syntax, (2) Scala tries to support too many paradigms, and (3)
the Iteratee library is hard to grasp.

For (1): I disagree -- Scala's syntax is relatively easy to grasp. Perhaps the
author meant constructs.

For (2): people keep saying this but why not just stick with the way you are
comfortable with?

For (3): I don't see how this is a language issue; at the very least it shows
that the author is unable to grasp a particular functional programming
abstraction.

~~~
jbergens
(1) I think you can safely assume that he means constructs. If he has spent
years writing Scala he has surely grasped the syntax. (2) A team may have many
people with different feelings about what they are comfortable with. This
raises problems in an enterprise environment. (3) I can only guess that he
feels the library is so hard that many developers with struggle with it.

I think Go is an interesting language partly because they seem to keep it
simple by choice.

------
kev6168
No offense to the author, but this reads like a 16 old claiming he finally
find the girl who is 'the one' for life. __only two years later__, that
Another girl shows up and OMG the new chick definitely is the 'true' one.

To put it another way, under extreme circumstances, Mr. Martin Odesky can use
even the $& _^%$#_ $ PHP to write safe and efficient airplane flying control
software.

The point is the language is hardly matter as much as your kids think. There
are far more important things for good software. But language is not only a
tool but also a toy and a passion, so I can appreciate the urge to talk about
it. :-)

~~~
nickik
> No offense to the author, but this reads like a 16 old claiming he finally
> find the girl who is 'the one' for his whole life.

I think thats what he was going for.

> There are far more important things for good software.

Everybody knows this, but people still like to talk about programming
languages.

~~~
thekingofspain
Additionally, I think what's key is to note that he wasn't pumping Clojure too
hard in the post. It was more a post about why he's leaving Scala. And in that
analogy, you can be pretty certain that the girl you're leaving is definitely
not "the one".

