
The truth about Scala - janm399
http://www.cakesolutions.net/teamblogs/2012/03/01/truth-about-scala/
======
enjo
Scala has been on my mind this week, so it was interesting to see this article
pop up. I've started to dive into an existing code-base, and I honestly just
can't grok what Scala is trying to be.

I think my biggest issue is that the language is so syntactically flexible
(verbose?) that I simply have no idea what is a language construct and what
isn't.

For instance the code is littered with stuff that looks like:

val something = some_obj open_!;

Is open_! just a method (literally some_obj.open_!) or is "_!" some sort of
language construct, because underscores are special sometimes, like with
unary_ for instance (or not.. it really just depends).

At first glance the 'almost any method can behave like an operator' stuff is
really cool, although as I learned about alarm bells where ringing all over
the place. In the hands of even an actually competent programmer it's going to
be abused well beyond the utility you get out of it.

It took 30 seconds of looking at existing code to find obvious examples of it.
Why is it so evil to clearly denote a method as being an actual method?

Then there is the whole "is this functional or not" madness. It reminds of
PERL in that respect. You can accomplish the same tasks in a bunch of
different ways.

I guess I'm not terribly impressed. It actually makes me long for the
simplicity of C. If you want static typing Scala (and readability adverse type
inference system) seems like a really bad choice. At least at the point I'm at
about a week into this stuff.

At the end of the day give me the beauty of C, the explicitness of Python, or
a much more complete functional language like Clojure. I don't want a hybrid
of all of those that seems to create a whole new set of weaknesses and big-
time issues. It really seems like the language designer merely looked at Java
and tried to create an interoperable language that was as "un-java-like" as
possible.

~~~
pron
I think I've figured Scala out. It's a statically typed JVM language meant to
be more powerful and at the same time easier to use than Java. It's a
functional language. Though, it's also imperative. And object-oriented. It
favors immutability, except that mutability is just as easy (or hard). It has
adopted the actor model. But it has also adopted all of Java's concurrency
constructs. It was designed as a very practical language. And it's also a
research language with some experimental features. Oh, I almost forgot: it is
meant to be a high-performance language. But it's also designed to build DSLs.
It's a very opinionated language in the sense that it's opinion is that all
opinions are valid.

So I must say that any difficulty you may have understanding what Scala is
trying to be is due to no fault of Scala itself. It's very simple, really
(well, to be precise, there are different tiers of simplicity in Scala, but I
can assure you that each tier is quite simple once you've mastered all the
design decisions, and category theory, that fully, consistently and self-
sufficiently define the simplicity of the respective tier).

~~~
ismarc
I explain why I think Scala will be giant to people by saying it is Java's
C++. It's as painful or nice as you want it, one company's use looks nothing
like another's and it is building on years of pain points to solve problems in
a different way while still using the current ecosystem(s).

~~~
michaelochurch
_Java's C++_

I would sell it that way to non-technical executives but not to anyone else.

I worked with someone who's a personal friend of Odersky and he's confident
that Scala _won't_ turn into C++. He described him as "way more scrupulous
than Stroustrup".

~~~
eternalban
It is too late for that.

~~~
mcguire
I have this sneaking suspicion that Scala has blown past C++ and is taking aim
on Perl.

------
nerd_in_rage
this mirrors my experience with scala, except we had about 100+ maven
dependencies and build times were closer to 10 minutes.

~~~
ismarc
This has been the opposite from my experience with Scala. Rather than build a
single system with a large codebase, it allows us to build small,
compartmentalized systems and compose them together. Then again, we don't use
maven, instead using ant for building and git submodules to handle
dependencies.

------
dkhenry
Reading through these comments I would like to point out this is an Aprils
fools day post. Its funny because if you didn't read to the end you might very
well believe it.

~~~
eta_carinae
> Reading through these comments I would like to point out this is an Aprils
> fools day post. Its funny because if you didn't read to the end you might
> very well believe it.

You know that Scala has gone off the deep end when somebody makes a parody
post of how complex it is and several people comment and say "Yup, that
totally matches my experience with Scala".

------
stcredzero
90 seconds is a build time issue? Kids these days don't know how good they
have it. It used to be time to go and grab a smoke to just _login_ to a box
with X-Windows. If our project always compiled in less than 300 seconds, we
were _golden_!

And yes, sounds like I'm imitating a hackneyed SNL skit, but everything here
is factual. I am indeed getting that old.

------
jvandenbroeck
On a serious note, is anything true from the post - if so, what parts? I find
the post funny but, I've started to learn Scala (I think it has some pretty
awesome features!) but if some of it is true, I might cancel my Scala-learning
mission.. :p

~~~
nessus42
Scala is awesome–you should definitely learn it.

Scala does provide you with enough rope to hang yourself with. What's the
solution to this? A. Don't hang yourself. New Scala shops should definitely
abide by the style guide that is provided at scala-lang.org to help with this.

Also, use implicits and multiple inheritance very judiciously. One thing that
is quite true from the OP, is that the "cake pattern" is indeed "the bakery of
doom". If you have to use dependency injection, use something sane, like
Guice. Or just ol' constructor injection.

My only big gripe with Scala is that OO syntax is a blight on the world. They
should have provided multi-methods instead, so everything could be done with
functional syntax.

~~~
eli_gottlieb
> _My only big gripe with Scala is that OO syntax is a blight on the world.
> They should have provided multi-methods instead, so everything could be done
> with functional syntax._

I actually disagree. Functional syntax means that you need to start using
qualified names or polluting your namespace (think of module/import usage in
Python, _but without OOP dot-notation_ ). I like being able to say:

    
    
        val herp: Option[Derp] = hurr()
        herp.getOrElse(Darpity)
    

Leaving aside the awful metasyntactic variables, the `getOrElse` method could
exist on any number of classes (stuff like `map` sure does!), but I never have
to use a qualified name to get the right one. I use dot-notation on the object
itself to qualify the method name.

~~~
chc
Do you find that's a problem with CLOS or Clojure multimethods? Because I
never noticed much of what you seem to be talking about.

~~~
eli_gottlieb
As I said above, think about a method like map.

    
    
        map :: [a] -> (a -> b) -> [b]
    

Well, actually, _any_ functor has a map method, by definition! So we'd have to
write a type-class:

    
    
        class Functor f where
          fmap :: f a -> (a -> b) -> f b
    

Now how would we represent this as a generic function?

    
    
        method fmap<a,b>(as: Functor<a>,f: a -> b): Functor<b>
    

And then implement specialized methods for each actual functor?

    
    
        override fmap<a,b>(as: List<a>,f: a -> b): List<b>
    

Now everything involving functors performs a dynamic dispatch and might lose
type information at its call-site, _and_ we now have to deal with Functor<a>
being some kind of superclass, a superclass without data slots of its own just
to accommodate our need for this "interface".

In Scala, rather than doing that, we would just define Functor[A] as a trait:

    
    
        trait Functor[A] self => {
          def map[B](f: A => B): self[A]
        }
    

And now every time I call the map method on a Scala object, it statically
dispatches via dot-notation. So my compiler knows that calling map on a
List[A] gives me back a List[B], _and_ that calling map on an Option[A] gives
me back an Option[B], _and_ I didn't need any implicits to get it done.

~~~
nessus42
I do not see why your worries cannot be addressed. In fact, IIRC (it's been a
while), the programming language Cecil does just that.

[http://www.cs.washington.edu/research/projects/cecil/www/cec...](http://www.cs.washington.edu/research/projects/cecil/www/cecil.html)

~~~
eli_gottlieb
Well, let me take a deeper look at the material. I've based most of my own
language work on multimethod systems like those of Cecil, but there's a few
things I immediately see on the page:

* Cecil divides its type system from its object-inheritance-overriding system. Huh?

* Cecil is dynamically typed with static sprinkles on top. So we have dynamic vtables, and also F-bounded polymorphism.

* Methods are referred to as being attached to objects, even though they are multimethods. This appears to imply _asymmetric_ multimethods. Again, _huh_? What a strange design decision to make!

* Cecil offers nothing for dealing with ad-hoc polymorphism (ie: operator overloading). Admittedly, when Cecil was published, type-classes didn't even exist yet.

~~~
nessus42
_Methods are referred to as being attached to objects, even though they are
multimethods. This appears to imply asymmetric multimethods. Again, huh? What
a strange design decision to make!_

Method dispatching is done _symmetrically_ on the arguments in Cecil.

~~~
eli_gottlieb
OK, I've read their doc now. And what I can say is, they don't solve the
problem I've mentioned at all. Their dot-notation is _just_ syntactic sugar
for an "ordinary" multimethod call. It does nothing for module selection.

This means you've got to either use qualified module names, make sure never to
import two modules that export an identically-named method, or (if the methods
have similar signatures) resort to a type-class.

~~~
nessus42
So??? This is how things work in Clojure. And that's just fine.

I guess I just don't understand where you are coming from. It's been pointed
out to you that Clojure hackers don't mind importing the generic functions.
You replied that then your worry is that it would be hard to preserve type
information in a statically typed language that works like Clojure. I
mentioned that Cecil is statically typed and preserves type information, with
a multi-method system that is somewhat similar to Clojure's. At least as I
understand it.

If your entire worry is that you have to import every generic function you
want to use, then I guess you and I just don't worry about the same things at
all. To me, importing the functions that you use is a _feature_ , not a bug!
In fact, when I program in Python, I generally program a lot more with
functions than with classes, and yes, in every module I explicitly import
every single externally defined function that that module needs. Again, I
consider this a feature, not a bug.

What I _would_ object to is having to explicitly import all the method
_definitions_ that implement the generic functions used in a multi-method
system. That would be insanity, but that's a moot point, as that is never
required, as far as I am aware.

Also, common generic functions, however, such as map(), could clearly be
automatically imported by the language. E.g., in Predef in Scala, or in built-
ins in Python. In fact, in Python, map() is in built-ins, and you don't have
to import it. Though, in Python's case, map() doesn't preserve the original
container type

~~~
eli_gottlieb
I'm not talking about importing the generic functions themselves at all. I'm
talking about importing the modules that export those generic functions, so
that I'll have the modules in my namespace to be able to name the generic
functions.

Again: dot-notation lets me write:

    
    
        import scala.collection.immutable.List
    
        def addn(n: Int) = (list: List[Int]) => list.map(_ + n)
    

Instead of:

    
    
        import scala.collection.immutable.List
    
        def addn(n: Int) = (list: List[Int]) => List.map(list,_ + n)
    

See the difference? And then, remember that map() is not a multimethod. It
doesn't actually do dynamic dispatch on its first argument, or on any other
argument. It's a type-class method; it does _static_ dispatch on the functor
type List[].

 _You cannot define map() as a generic function_ , at least not in the sense
that Common Lisp and Clojure use the term "generic function".

It can be conveniently expressed as a type-class method of a class 'Functor f
:: * -> * ' or a trait method for a Functor[A]. _Not_ a generic function.

~~~
nessus42
> _I'm not talking about importing the generic functions themselves at all.

> I'm talking about importing the modules that export those generic functions,

> so that I'll have the modules in my namespace to be able to name

> the generic functions._

I don't see how this is either here or there. I can import modules and then
qualify functions within the modules, or I can import functions directly from
the modules, renaming then if I want to. There's no difference, between these
options, other than a minor difference in what name I use to refer to the
function once its been imported.

> Again: dot-notation lets me write:

> import scala.collection.immutable.List

> def addn(n: Int) = (list: List[Int]) => list.map(_ + n)

> Instead of:

> import scala.collection.immutable.List

> def addn(n: Int) = (list: List[Int]) => List.map(list,_ + n)

It isn't dot notation that lets you do that; it's the semantics of how
functions are located that lets you do that. Many languages support statically
overloaded functions using functional notation. It's also quite easy to
imagine a language which uses the syntax f(a) to mean what a.f() means in
Scala.

Also, why is this to be considered so desirable? For the performance gain that
comes from eliminating dynamic dispatch? In that case, it is certainly
possible for a language that supports multiple dispatch to dispatch statically
when it can infer that it is safe to do.

> See the difference?

Yes, I quite understand the concept, but it has nothing intrinsically to do
with dot notation.

> And then, remember that map() is not a multimethod.

> It doesn't actually do dynamic dispatch on its first argument,

> or on any other argument. It's a type-class method; it does static dispatch

> on the functor type List[].

In Scala? I don't believe that this is correct. As far as I understand,
there's a single implementation of map for the entire collection library in
TraversableLike, which uses virtual functions provided by the concrete class
(and a builder object which gets passed in implicitly) to construct the new
container, loop over the old container, and add elements to the new container.

This is similar to how map() works in Python and Clojure, where there is a
single implementation of map() which uses dynamic dispatch to loop over the
elements of the container. The downside to the way that Python and Clojure
doing things is that you get iterators or streams back, not the original
container type. But they could return the original container type if
containers in Python and Clojure were to have virtual constructors. Then map()
could call these virtual constructors to return a container of the same type.

> You cannot define map() as a generic function, at least not in the sense
> that

> Common Lisp and Clojure use the term "generic function".

Clearly in a statically typed language, you also need some form of parametric
polymorphism in addition to what Common Lisp and Clojure provide in order to
preserve types. I see no reason why this should be insurmountable.

I've often done things in C++ that wrapped dynamic lookup in a generic
function or class, to achieve the types of things that you say require type
classes. Another thing you can easily do in C++ is to write template adapter
classes to provide something similar to Scala's structural types.

Also, type classes surely don't require dot notation. Haskell is from where
type classes originate, and Haskell doesn't have dot notation.

~~~
eli_gottlieb
_Also, why is this to be considered so desirable?_

To avoid namespace pollution.

~~~
nessus42
I just want to reiterate how completely a non-issue this is. It is so much of
a non-issue, that it took me this long to even get the slightest inkling of
what your worry is.

The reason that it is a non-issue is how often do you need to import two
external functions with the same name that have different meaning into the
same file at the same time? It _does_ happen, but not so much that it is an
issue.

With Python, for instance, there is sys.path and os.path. So what? I refer to
one as sys.path and the other as os.path. BFD. And there's the join method on
strings and os.path.join. Since one's a method and the other's a function in
Python, you're right that if methods were called like functions in Python,
there'd be a potential namespace conflict, but I'd just continue to refer to
one as join and the other as path.join. I do that now anyway, so _nothing_
would change!

Or let's take the example of draw. If we're only talking about drawing to the
screen, then all of the draw methods can implement a common generic function.
There's no problem. On the other hand, if I need to use both the "draw on the
screen" draw and the "draw your gun" draw, then I'd import one as drawOnScreen
and the other as drawYourGun.

If overloading in supported, then there's no need even to do renaming. You can
just use draw all the time and the type system will know which draw is
applicable for the type in question.

Once again, no problem.

In summary, your worry is just not a problem!

------
mindslight
Tying a new language to the JVM _is_ basically like helping a drowning man by
throwing him an anchor. Scala the language is decent, but the JVM-induced
clusterfuck of complex stdlib/IDE reliance/maven makes for a non-starter.

~~~
eta_carinae
> Scala the language is decent, but the JVM-induced clusterfuck of complex
> stdlib/IDE reliance/maven makes for a non-starter.

I see things the other way around: the JVM is a very impressive piece of
technology that has been aging impressively well for more than fifteen years
while Scala is a C++-like monstrosity that will probably be all but forgotten
in a few years.

Personally, I'm more interested in the new crop of JVM languages such as
Kotlin.

------
liftup
Some could be taking this article a bit too serious. I self taught myself to
code 6 months ago and like enjo stated it seems very littered and perhaps too
flexible.

------
ilcavero
Why does a scala centric company publishes such a poor flame bait article
against scala? I think this is just a joke and not to be taking seriously in
any way

~~~
meow
well it does say "happy april fools day the end" :)

~~~
devin
Yeah, but... it's not funny. It seems like some of it might be true.

~~~
ilcavero
that's my point is not funny at all and as serious criticism is pointless and
destructive

~~~
kev009
You're not allowed to point out deficiencies in something you like and
advocate? That's a fairly dense position..

The nice thing about Open Source is that it tends to be a little bit more
immune to that corporate drum beat since there are less full time salesmen and
marketeers. The void seems to fill with fanbois though.

~~~
ilcavero
I would have loved to see what these guys have to say about Scala critically,
but that's not what they are doing, this is a half baked unfunny joke that
does not inspire any debate, only flaming and bashing. Is good that you talk
about fanboyism because that's what this article is about, clojure fanboyism
to be precise

~~~
manorasa
The article is funny BECAUSE it's true.

I love Scala and have been using it for a couple of years but I've been
through nearly all the stages described in the article. Eventually I got so
frustrated I gave up and learned Clojure !!

