61

What are the most commonly held misconceptions about the Scala language, and what counter-examples exist to these?

UPDATE

I was thinking more about various claims I've seen, such as "Scala is dynamically typed" and "Scala is a scripting language".

I accept that "Scala is [Simple/Complex]" might be considered a myth, but it's also a viewpoint that's very dependent on context. My personal belief is that it's the very same features that can make Scala appear either simple or complex depending oh who's using them. Ultimately, the language just offers abstractions, and it's the way that these are used that shapes perceptions.

Not only that, but it has a certain tendency to inflame arguments, and I've not yet seen anyone change a strongly-held viewpoint on the topic...

Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
Kevin Wright
  • 49,540
  • 9
  • 105
  • 155

13 Answers13

40

Myth: That Scala’s “Option” and Haskell’s “Maybe” types won’t save you from null. :-)

Debunked: Why Scala's "Option" and Haskell's "Maybe" types will save you from null by James Iry.

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • Scala option types do save you from null. You can think of an option type as a null pointer you have to "null check" to derefer. Since it's impossible to use an "Option[a]" like an "a", Option types will make sure that null pointer exceptions never occur. Iry's article is basically missing that point. – keiter Oct 13 '10 at 18:12
  • Nevermind. Shows my reading comprehension eh? :) – keiter Oct 13 '10 at 18:18
  • 1
    That's only partly true I think. The reference to the Option itself can be null, as well as the value in it (it can be Some(null)). There's nothing that prevents that. – Arjan Blokzijl Oct 13 '10 at 18:28
  • 2
    Perhaps Option should extend the NotNull trait? –  Oct 13 '10 at 22:42
  • 4
    With the disclaimer that Option only helps if it's actually used. You can still get nulls in Scala, especially where Java interop is involved. – Kevin Wright Oct 17 '10 at 21:58
  • 1
    Isn't `Null` is a subtype of all `AnyRef` types? Doesn't that mean that any reference can be null? – Gabe Oct 18 '10 at 04:08
  • @Gabe: Yes, they can. Read the Postscript in James Iry's above-linked article for clarification on this. – missingfaktor Oct 18 '10 at 06:15
  • missingfaktor: So he's saying that even though nulls are possible, in practice they're rarely a problem? I think the myth is still correct. While idiomatic Scala uses `Option` types to avoid nulls, you stil have to worry about them when interacting with any Java code. – Gabe Oct 18 '10 at 06:40
  • 2
    @Gabe: Agreed, but that doesn't validate the statement "Scala's `Option` type won't save you from nulls". It certainly will, provided you use it. – missingfaktor Oct 18 '10 at 06:50
37

Myth: Scala supports operator overloading.

Actually, Scala just has very flexible method naming rules and infix syntax for method invocation, with special rules for determining method precedence when the infix syntax is used with 'operators'. This subtle distinction has critical implications for the utility and potential for abuse of this language feature compared to true operator overloading (a la C++), as explained more thoroughly in James Iry's answer to this question.

Community
  • 1
  • 1
Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
  • This one gets my vote for answering the question. Mostly because it's the sort of answer I was looking for. A widespread myth that's absolutely and objectively false, and one which leads to a misunderstanding of the language and its complexity. But it's a community wiki, so keep 'em coming! – Kevin Wright Oct 17 '10 at 11:48
  • @Kevin: You mean others (including myself) didn't answer the question?! – missingfaktor Oct 17 '10 at 16:11
  • 1
    @missingfactor: sure you did, but SO was nagging me to accept just one answer... This one seemed to best represent the kind of well-intentioned-but-ultimately-misinformed statements about Scala that I was seeking with my question. – Kevin Wright Oct 17 '10 at 16:32
  • I can see where this is coming from, but I think the answer could do much better if it explained the basic difference of the single-dispatch method in Scala to the full compile-time "static method" overloading allowed by C++. –  Apr 16 '11 at 19:26
33

Myth: methods and functions are the same thing.

In fact, a function is a value (an instance of one of the FunctionN classes), while a method is not. Jim McBeath explains the differences in greater detail. The most important practical distinctions are:

  • Only methods can have type parameters
  • Only methods can take implicit arguments
  • Only methods can have named and default parameters
  • When referring to a method, an underscore is often necessary to distinguish method invocation from partial function application (e.g. str.length evaluates to a number, while str.length _ evaluates to a zero-argument function).
Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
  • +1 This is not pointed out enough. Many people forget that the *scope* (class body or function body, etc.) of `def` is also very important to this distinction as of what the underlying mechanism used is. –  Apr 16 '11 at 19:28
32

I disagree with the argument that Scala is hard because you can use very advanced features to do hard stuff with it. The scalability of Scala means that you can write DSL abstractions and high-level APIs in Scala itself that otherwise would need a language extension. So to be fair you need to compare Scala libraries to other languages compilers. People don't say that C# is hard because (I assume, don't have first hand knowledge on this) the C# compiler is pretty impenetrable. For Scala it's all out in the open. But we need to get to a point where we make clear that most people don't need to write code on this level, nor should they do it.

Martin Odersky
  • 20,470
  • 9
  • 51
  • 49
  • 17
    One of things I'm enjoying most about learning Scala (and gradually infecting my Java codebase with it) is that while at one level it can be very clean and straightforward and even pleasurable to code in, there are so many other powerful levels to explore. Some of those latter features are still beyond me, but that just means I have things to learn, which is cool! And if that power results in the occasional bullet hole in my shoe, well, Scala restricts me to a six-shooter, unlike, say, the Uzi that Perl provides. ;-) – Rodney Gitzel Oct 13 '10 at 18:22
  • 4
    I can't help but agree. If a tool is complicated because it allows you to make complex things, then you'd also have to include both minecraft and lego under such a definition. This feels very counter-intuitive to me. – Kevin Wright Oct 14 '10 at 16:48
  • 7
    There this very nice post by Martin him self: http://lamp.epfl.ch/~odersky/blogs/isscalacomplex.html – pedrofurla Oct 21 '10 at 01:03
29

I think a common misconception amongst many scala developers, those at EPFL (and yourself, Kevin) is that "scala is a simple language". The argument usually goes something like this:

  • scala has few keywords
  • scala reuses the same few constructs (e.g. PartialFunction syntax is used as the body of a catch block)
  • scala has a few simple rules which allow you to create library code (which may appear as if the language has special keywords/constructs). I'm thinking here of implicits; methods containing colons; allowed identifier symbols; the equivalence of X(a, b) and a X b with extractors. And so on
  • scala's declaration-site variance means that the type system just gets out of your way. No more wildcards and ? super T

My personal opinion is that this argument is completely and utterly bogus. Scala's type system taken together with implicits allows one to write frankly impenetrable code for the average developer. Any suggestion otherwise is just preposterous, regardless of what the above "metrics" might lead you to think. (Note here that those who I've seen scoffing at the non-complexity of Java on Twitter and elsewhere happen to be uber-clever types who, it sometimes seems, had a grasp of monads, functors and arrows before they were out of short pants).

The obvious arguments against this are (of course):

  1. you don't have to write code like this
  2. you don't have to pander to the average developer

Of these, it seems to me that only #2 is valid. Whether or not you write code quite as complex as scalaz, I think it's just silly to use the language (and continue to use it) with no real understanding of the type system. How else can one get the best out of the language?

nedim
  • 1,767
  • 1
  • 18
  • 20
oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
  • 8
    I think I'd phrase my own belief as "scala doesn't have to be complex", rather than "scala is simple". Given the Turing-complete potential for obfuscation, any language can be made complicated if you so choose. Scala has a lot of potential for KISS design without a heavy burden of boilerplate, and that's no bad thing! – Kevin Wright Oct 13 '10 at 17:44
  • Is there a language which doesn't even allow one to write impenetrable code? – Ken Oct 13 '10 at 18:03
  • And brain**** of course? @Kevin - I think you'd want to hire a scala developer who was able to understand complicated code gymnastics for 2 reasons: firstly that they may come across this sort of code. Secondly; they may have cause to use it to solve a problem in an optimal way. – oxbow_lakes Oct 13 '10 at 20:30
  • 4
    "the equivalence of X(a, b) and a X b"? Nope, the equivalence is a.X(b) and a X b. – Landei Oct 13 '10 at 21:30
  • 2
    The argument based on keywords and such is at least more substantive than "look at this example of obfuscated code." –  Oct 13 '10 at 23:49
  • 1
    @Landei - I suggest you go and read the language spec before being so dismissive. How do you think you can pattern match on `x :: xs`? It is because, for an extractor, this is equivalent to matching on `::(x, xs)` – oxbow_lakes Oct 14 '10 at 08:05
  • @MJP - the point is that scalaz is not *intentionally* obfuscated. Neither is the new collections library, but they are still complicated to understand – oxbow_lakes Oct 14 '10 at 08:06
  • 1
    This sounds lots like what's the major issue with C++. It's possible to keep C++ code understandable, yes. In practice it requires limiting which language features are used in a particular project/organization, because otherwise other developers will write code that you don't understand and vice versa. Unfortunately this also prevents getting the best out of the language in the real world. I have not yet seen a *too simple* language. Too complicated, many of them... – Joonas Pulakka Oct 14 '10 at 08:09
  • 1
    @oxbow_lakes: Normally `x :: xs` is evaluated as `xs.::(x)`, which is essentially the same as I specified (just with the special colon-rule for reversing the arguments). Of course you are right concerning extractors and I didn't thought about that, but you have to admit that method calls are much more common, that new users often trip about that, and that you usually use the 'symmetric' extractor syntax for special chars and not for letters. – Landei Oct 14 '10 at 09:15
  • 3
    @Landei - *sighs*. You are wrong. Try it, or just look at this answer from Daniel: http://stackoverflow.com/questions/1059145/how-is-this-case-class-match-pattern-working/1059161#1059161 – oxbow_lakes Oct 14 '10 at 10:21
  • 1
    scala> case class X(i : Int, s : String) – oxbow_lakes Oct 14 '10 at 10:26
  • 2
    @oxbow_lakes: Did you actually **read** my answer? I already said you were right concerning extractors and pattern matching, just from the way you wrote it wasn't very obvious what you meant (at least not to me). But there **are** two methods defined in List: `def :: (x: A): List[A]` and `def ::[B >: A](x: B): List[B]`, and they are the normal "use case" (when you are not pattern matching), and work as I stated, so I suggest you go and read the ScalaDocs before being so self-confident. – Landei Oct 14 '10 at 14:00
  • @Landei - indeed; I should have read the full comment. Apologies – oxbow_lakes Oct 14 '10 at 16:34
  • @oxbow_lakes: And I admit that my initial comment was too flippant, sorry for that. – Landei Oct 14 '10 at 17:13
  • 1
    From my experience, in informatics, many times you have no option than to learn "by need" or "by demand". Given the examples I have seen about scalaz I haven't had any need (or motivation) to learn it... – gerferra Oct 14 '10 at 20:21
  • @german1981 - I'm not necessarily saying that you need to learn scalaz. But you might (for example) want to understand a bit more about how to get round scala's lack of partially applied type constructors. Or perhaps just a sounder grounding in FP. You should certainly understand about typeclasses (in my opinion). – oxbow_lakes Oct 15 '10 at 08:15
  • I'd say: the *language* is simple, the *semantics* is not (in particular because of the type system). – Raphael Jan 25 '11 at 21:08
  • @Raphael You seem to be equating the language to its syntax or grammar -- the very mistake that oxbow_lakes is addressing. – Jim Balter Feb 20 '11 at 20:33
  • But that is what is a (formal) language in computer science is: Syntax, given e.g. by a grammar. The term "programming language" subsumes formal language (syntax), static semantics and dynamic semantics. I think it is worthwhile to separate those concepts and not a mistake. – Raphael Feb 20 '11 at 21:07
20

There is a myth that Scala is difficult because Scala is a complex language.

This is false--by a variety of metrics, Scala is no more complex than Java. (Size of grammar, lines of code or number of classes or number of methods in the standard API, etc..)

But it is undeniably the case that Scala code can be ferociously difficult to understand. How can this be, if Scala is not a complex language?

The answer is that Scala is a powerful language. Unlike Java, which has many special constructs (like enums) that accomplish one particular thing--and requires you to learn specialized syntax that applies just to that one thing, Scala has a variety of very general constructs. By mixing and matching these constructs, one can express very complex ideas with very little code. And, unsurprisingly, if someone comes along who has not had the same complex idea and tries to figure out what you're doing with this very compact code, they may find it daunting--more daunting, even, than if they saw a couple of pages of code to do the same thing, since then at least they'd realize how much conceptual stuff there was to understand!

There is also an issue of whether things are more complex than they really need to be. For example, some of the type gymnastics present in the collections library make the collections a joy to use but perplexing to implement or extend. The goals here are not particularly complicated (e.g. subclasses should return their own types), but the methods required (higher-kinded types, implicit builders, etc.) are complex. (So complex, in fact, that Java just gives up and doesn't try, rather than doing it "properly" as in Scala. Also, in principle, there is hope that this will improve in the future, since the method can evolve to more closely match the goal.) In other cases, the goals are complex; list.filter(_<5).sorted.grouped(10).flatMap(_.tail.headOption) is a bit of a mess, but if you really want to take all numbers less than 5, and then take every 2nd number out of 10 in the remaining list, well, that's just a somewhat complicated idea, and the code pretty much says what it does if you know the basic collections operations.

Summary: Scala is not complex, but it allows you to compactly express complex ideas. Compact expression of complex ideas can be daunting.


There is a myth that Scala is non-deployable, whereas a wide range of third-party Java libraries can be deployed without a second thought.

To the extent that this myth exists, I suspect it exists among people who are not accustomed to separating a virtual machine and API from a language and compiler. If java == javac == Java API in your mind, you might get a little nervous if someone suggests using scalac instead of javac, because you see how nicely your JVM runs.

Scala ends up as JVM bytecode, plus its own custom library. There's no reason to be any more worried about deploying Scala on a small scale or as part of some other large project as there is in deploying any other library that may or may not stay compatible with whichever JVM you prefer. Granted, the Scala development team is not backed by quite as much force as the Google collections, or Apache Commons, but its got at least as much weight behind it as things like the Java Advanced Imaging project.

Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • 14
    A Dijkstra quote seems appropriate here: *Programming will remain very difficult, because once we have freed ourselves from the circumstantial cumbersomeness, we will find ourselves free to tackle the problems that are now well beyond our programming capacity.* Could it be the case that Scala removes enough of the cumbersomeness that we're simply now seeing it being used for inherently more complicated problems, and it's this complexity which is being associated with the language? – Kevin Wright Nov 27 '10 at 18:21
16

Myth:

def foo() = "something"

and

def bar = "something"

is the same.

It is not; you can call foo(), but bar() tries to call the apply method of StringLike with no arguments (results in an error).

Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
Arne
  • 7,921
  • 9
  • 48
  • 66
15

Some common misconceptions related to Actors library:

  • Actors handle incoming messages in a parallel, in multiple threads / against a thread pool (in fact, handling messages in multiple threads is contrary to the actors concept and may lead to racing conditions - all messages are sequentially handled in one thread (thread-based actors use one thread both for mailbox processing and execution; event-based actors may share one VM thread for execution, using multi-threaded executor to schedule mailbox processing))
  • Uncaught exceptions don't change actor's behavior/state (in fact, all uncaught exceptions terminate the actor)
Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
  • 1
    Could you be more specific about the first point? Does "actor is represented with one thread" mean: 1) it is always run by one and the same worker thread 2) it is run by one thread at a time, but the same actor may at different points be run on different threads (i.e. after blocking, it may later be run on some other thread) Note that this has an impact on certain things - for instance, can you safely use ThreadLocals with actors? – axel22 Oct 13 '10 at 18:01
  • 5
    In a basic configuration, Scala actor is backed with ThreadPoolExecutor (ExecutorScheduler). It's ensured that suspended actor will be resumed on the same thread. When actor is backed with SingleThreadScheduler, all actor tasks are executed on the same single thread. – Vasil Remeniuk Oct 13 '10 at 18:58
  • Nice. I didn't know its ensured they get executed on the same worker thread. Thanks! – axel22 Oct 13 '10 at 20:17
  • 2
    Many people confuse concurrency and parallelism in general. It might be the underlying misconception here, too. – Raphael Jan 25 '11 at 21:09
  • 1
    @axel22 It depends upon configuration. Each actor could -- if setup so -- run on its own dedicated thread. However, then it'd be back up to the n threads for n actors situation. On the other hand, blocking IO in actors can make for some not-fun situations if not anticipated ;-) –  Apr 16 '11 at 19:03
15

Myth: You can replace a fold with a reduce when computing something like a sum from zero.

This is a common mistake/misconception among new users of Scala, particularly those without prior functional programming experience. The following expressions are not equivalent:

seq.foldLeft(0)(_+_)

seq.reduceLeft(_+_)

The two expressions differ in how they handle the empty sequence: the fold produces a valid result (0), while the reduce throws an exception.

Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
  • Interestingly enough, `reduceLeft` works on (Int) sequences with one element. Does it use the default (Int) value for that? If so, why does `Seq[Int]().reduceLeft(_+_)` not work? And why do we all miss `sum` time and again? ;) – Raphael Jan 25 '11 at 21:15
  • No, reduce doesn't use a default value on sequences with one element; it just returns the first (i.e. only) element. `seq.reduceLeft(f)` is roughly equivalent to `seq.tail.foldLeft(seq.head)(f)`. – Aaron Novstrup Jan 25 '11 at 22:59
  • Thanks. In this case, the current documentation is at least incomplete, i.e. it does not specify behaviour on empty and one-element traversables. So are those for foldX. I can not think of a concrete and non-pathological example right now, but can we be certain (in general) that this base case is always compatible to behaviour on longer collections? In particular, the passed function can return instances of `B != A`, so `Seq(a,zero).reduceLeft(_+_) != Seq(a).reduceLeft(_+_)` for some `+` and `zero` the according "neutral" element? – Raphael Jan 26 '11 at 16:00
  • Demanding that parameters of functions used in such aggregator functions have default values is no (general) solution, I guess. Would it be possible to utilize them if present (in the implementation of the aggregators)? – Raphael Jan 26 '11 at 16:03
  • @Raphael Regarding your first question, I'm sure you can prove your "compatibility" property provided some assumptions about `+` and `zero` (such as identity of the `zero` with respect to `+`: `a` + `zero` = `a` = `zero` + `a` for all `a`). – Aaron Novstrup Jan 26 '11 at 17:47
  • @Raphael Regarding your second question, it isn't possible for the aggregator function to utilize default values for reduce because the aggregator is never invoked on an empty collection. That is, reduce is undefined on the empty collection, irrespective of the aggregator. – Aaron Novstrup Jan 26 '11 at 17:49
  • 1) Exactly. But the compiler can't check that. So the programmer has to take care; in this case, documentation should clearly state state what happens resp. what properties the passed function must have. 2) Sure, that's the point. Can we check wether default values are supplied, and if, apply it? – Raphael Jan 26 '11 at 19:15
  • 1) I think that's outside the scope of the documentation of the reduce function, since reduce is far more general than just computing sums. Reduce can be (and is) defined with no reference to a `+` or `0`, so it makes no sense for the documentation to define what these notions might mean. If a programmer is using reduce to compute an aggregation, it's up to him to make sure that it satisfies the properties that he wants it to satisfy. Note that some useful aggregations won't satisfy your property (e.g. `strings.reduceLeft(_ + ", " + _)`). – Aaron Novstrup Jan 26 '11 at 19:56
  • 2) It seems you mean "in the implementation of `reduceLeft`" rather than "in the implementation of aggregators". In this case, yes, `reduceLeft` could easily be defined so that it would utilize default values. However, that will never happen in the standard library because `reduce` is a well-known function from functional programming, and it's important that its semantics are consistent with other languages (principle of least surprise). – Aaron Novstrup Jan 26 '11 at 20:03
  • See also http://en.wikipedia.org/wiki/Fold_(higher-order_function) – Aaron Novstrup Jan 26 '11 at 20:21
12

Myth: Pattern matching doesn't fit well with the OO paradigm.

Debunked here by Martin Odersky himself. (Also see this paper - Matching Objects with Patterns - by Odersky et al.)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
missingfaktor
  • 90,905
  • 62
  • 285
  • 365
10

Myth: this.type refers to the same type represented by this.getClass.

As an example of this misconception, one might assume that in the following code the type of v.me is B:

trait A { val me: this.type = this }

class B extends A

val v = new B

In reality, this.type refers to the type whose only instance is this. In general, x.type is the singleton type whose only instance is x. So in the example above, the type of v.me is v.type. The following session demonstrates the principle:

scala> val s = "a string"
s: java.lang.String = a string

scala> var v: s.type = s
v: s.type = a string

scala> v = "another string"
<console>:7: error: type mismatch;
 found   : java.lang.String("another string")
 required: s.type
       v = "another string"
Aaron Novstrup
  • 20,967
  • 7
  • 70
  • 108
7

Scala has type inference and refinement types (structural types), whereas Java does not.

The myth is busted by James Iry.

Vasil Remeniuk
  • 20,519
  • 6
  • 71
  • 81
  • I guess the author confuses anonymous classes and refinement types https://stackoverflow.com/questions/75149674/what-is-a-difference-between-refinement-type-and-anonymous-subclass-in-scala-3 – Dmytro Mitin Apr 08 '23 at 09:35
3

Myth: that Scala is highly scalable, without qualifying what forms of scalability.

Scala may indeed be highly scalable in terms of the ability to express higher-level denotational semantics, and this makes it a very good language for experimentation and even for scaling production at the project-level scale of top-down coordinated compositionality.

However, every referentially opaque language (i.e. allows mutable data structures), is imperative (and not declarative) and will not scale to WAN bottom-up, uncoordinated compositionality and security. In other words, imperative languages are compositional (and security) spaghetti w.r.t. uncoordinated development of modules. I realize such uncoordinated development is perhaps currently considered by most to be a "pipe dream" and thus perhaps not a high priority. And this is not to disparage the benefit to compositionality (i.e. eliminating corner cases) that higher-level semantic unification can provide, e.g. a category theory model for standard library.

There will possibly be significant cognitive dissonance for many readers, especially since there are popular misconceptions about imperative vs. declarative (i.e. mutable vs. immutable), (and eager vs. lazy,) e.g. the monadic semantic is never inherently imperative yet there is a lie that it is. Yes in Haskell the IO monad is imperative, but it being imperative has nothing to with it being a monad.

I explained this in more detail in the "Copute Tutorial" and "Purity" sections, which is either at the home page or temporarily at this link.

My point is I am very grateful Scala exists, but I want to clarify what Scala scales and what is does not. I need Scala for what it does well, i.e. for me it is the ideal platform to prototype a new declarative language, but Scala itself is not exclusively declarative and afaik referential transparency can't be enforced by the Scala compiler, other than remembering to use val everywhere.

I think my point applies to the complexity debate about Scala. I have found (so far and mostly conceptually, since so far limited in actual experience with my new language) that removing mutability and loops, while retaining diamond multiple inheritance subtyping (which Haskell doesn't have), radically simplifies the language. For example, the Unit fiction disappears, and afaics, a slew of other issues and constructs become unnecessary, e.g. non-category theory standard library, for comprehensions, etc..

miken32
  • 42,008
  • 16
  • 111
  • 154
Shelby Moore III
  • 6,063
  • 1
  • 33
  • 36