Scala FAQ


Frequently asked questions, with brief answers and/or links to longer answers.

This list only includes questions that actually come up over and over again in Scala chat rooms and forums.

General questions

Where can I ask Scala questions?

See our Community page.

What’s a good book about Scala?

Our Books page lists a few especially popular, well-known books.

We don’t have a list of all the Scala books that are out there; there are many.

You can go on the #scala-users room on Discord or another community forum and ask for book recommendations. You’ll get more helpful answers if you provide some information about your background and your reasons for wanting to learn Scala.

Should I learn Scala 2, or Scala 3?

Don’t sweat the decision too much. You can’t go far wrong either way. It isn’t that hard to switch later, in either direction.

Scala 2 remains a common and reasonable choice. Most Scala jobs are still Scala 2 jobs. Scala 2 also has a somewhat bigger library ecosystem, somewhat better tooling support, and somewhat wider availability of learning materials.

That said, these gaps are getting narrower every month. Plenty of books are available, a rich library ecosystem already exists, and there are more and more jobs using Scala 3. You should strongly consider learning Scala 3. It’s still fairly new, released in 2021. But it’s the future, and it’s the best version for falling in love with the language and everything it has to offer.

Where are Scala jobs advertised?

This is addressed on our Community page.

In short, the only officially sanctioned place is the #jobs channel on Discord.

Who’s behind Scala?

This is answered on the community page.

See scala/scala-lang#1040.

Technical questions

The list of available options is here.

What flags people choose varies widely from shop to shop and from individual to individual. -Xlint is valuable to enable. Some brave people enable -Werror (formerly -Xfatal-warnings) to make warnings fatal.

sbt-tpolecat is an opinionated sbt plugin that sets many options automatically, depending on Scala version; you can see here what it sets. Some choices it makes are oriented towards pure-functional programmers.

How do I find what some symbol means or does?

A Stack Overflow answer lays out what the different kinds of symbol in Scala are and explains the most commonly used symbols.

Scala allows symbolic method names. So if you see a random-looking operator like >=@=> in Scala code, it might simply be a method in some library, rather than having any special meaning in the language itself.

You can search for symbols on Google. For example, if you want to know what <:< means, searching for scala <:< works fine. If you get poor results, try surrounding the symbol with double quotes.

I want Scala 2.13 (or some other version); why does sbt say it’s using Scala 2.12?

sbt 1.x always uses Scala 2.12 to compile build definitions. Your sbt 1.x build definition is always a Scala 2.12 program.

Regardless, in your build.sbt, you can set scalaVersion to whichever available distribution you want and your program code will be compiled with that version.

I want Scala 3. Why does versionNumberString say I’m on 2.13?

To aid migration, Scala 3 currently uses the Scala 2.13 library as-is, with only minor supplements. That’s why versionString and versionNumberString report that Scala 2 is in use:

Welcome to Scala 3.3.3 (17.0.3, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> util.Properties.versionNumberString
val res0: String = 2.13.12

Note that even the latest Scala 3 version might not use the very latest Scala 2 standard library, since the 3 and 2 release schedules aren’t coordinated.

So how do you ask for the Scala 3 version number? Scala 3 offers, but only if you have scala3-compiler on the classpath. So that works in the Scala 3 REPL, but won’t work in typical Scala 3 application code.

For an alternative way to detect the Scala 3 version, see this gist.

Why is my (abstract or overridden) val null?

See this.

Which type of collection should I choose?

See the Scala 2.13 Collections Guide.

What are context bounds?

It’s syntactic sugar for a context parameter (an implicit parameter in Scala 2, or a using parameter in Scala 3).

More details in this section of the Scala 3 Book and this Stack Overflow answer.

How does for / yield work?

It is syntactic sugar for nested map, flatMap, and withFilter calls.

For an in-depth explanation see this Stack Overflow answer.

What is the difference between view, stream and iterator?

Answer on Stack Overflow.

What does _ mean?

Many things really, depending on the context. This answer on Stack Overflow has a good summary of all the meanings it has.

Note that, even if the specific meaning is different, according to the situation, it usually means “anything”.

Why doesn’t my function literal with _ in it work?

Not all function literals (aka lambdas) can be expressed with the _ syntax.

Every occurrence of _ introduces a new variable. So _ + _ means (x, y) => x + y, not x => x + x. The latter function cannot be written using the _ syntax.

Also, the scope of _ is always the smallest enclosing expression. The scope is determined purely syntactically, during parsing, without regard to types. So for example, foo(_ + 1) always means foo(x => x + 1); it never means x => foo(x + 1). The latter function cannot be written using the _ syntax.

See also SLS 6.23.2.

Why couldn’t Scala infer the correct type in my code?

It is difficult to generalize about type inference, because various features of the language affect how your code is construed. There may be several ways to rewrite your code to make the types fall out naturally.

The most straightforward workaround is to supply explicit types in your code.

That may involve specifying an explicit type to a definition, or a type argument to a method.

Type inference is greatly improved in Scala 3. If Scala 2 doesn’t compile your code, it’s worth trying with Scala 3.

Sometimes, using multiple parameter lists helps inference, as explained in this section of the language tour.

For common questions about type inference involving toSet, see the discussions on this ticket and a related Q&A.

Can I chain or nest implicit conversions?

Not really, but you can make it work.

However, note that implicit conversions are, in general, discouraged.

Where does Scala look for implicits?

See this answer on Stack Overflow.

Why do primitive type parameters erase to Object?

So for example, a List[Int] in Scala code will appear to Java as a List[Object]. The Java type system doesn’t allow primitive types to appear as type parameters, but couldn’t they appear as their boxed equivalents, such as List[java.lang.Integer]?

One would hope so, but doing it that way was tried, and it proved impossible. This SO question sadly lacks a concise explanation, but it does link to past discussions.

What’s the difference between methods and functions?

For example, how does a method such as:

def square(x: Int): Int = x * x

differ from a function value such as:

val square: Int => Int = x => x * x

For Scala 2, there is a complete answer on Stack Overflow and a summary with practical differences.

Note that in Scala 3 the differences are fewer; for example, they will be able to accept implicit parameters as well as type parameters.

Nevertheless, it is still recommended to use methods most of the time, unless you absolutely need a function. And, thanks to eta-expansion you rarely would need to define a function rather than a method.

What’s the difference between types and classes?

Types are primarily a compile-time concept. At compile time, every expression is assigned a type by the compiler.

Classes are primarily a runtime concept and are platform-dependent. At runtime on the JVM, every value is either a primitive value or an instance of exactly one class.

Some type information exists only at compile time, for multiple reasons, most notoriously type erasure.

For an in-depth treatment of types vs. classes, see the blog post “There are more types than classes”.

How can a method in a superclass return a value of the “current” type?

First, note that using this.type won’t work. People often try that, but this.type means “the singleton type of this instance”, a different and too-specific meaning. Only this itself has the type this.type; other instances do not.

What does work? Possible solutions include F-bounded polymorphism (familiar to Java programmers), type members, and the typeclass pattern.

This blog post argues against F-bounds and in favor of typeclasses; see also this Stack Overflow post for some counterpoint.

What does <:< mean?

It’s a “type constraint”, and it comes from the standard library, not from the language itself. See this blog post.

I dislike requiring callers to wrap optional arguments in Some(...); is there a better way?

Not really. See this answer on Stack Overflow.

The latter has a singleton type, which is too specific. See answer on Stack Overflow.

I got a StackOverflowError while compiling my code. Is it a compiler bug?

It might be.

To find out, try giving the compiler more stack and see if the error goes away.

It’s possible for the compiler to run out of stack when compiling some kinds of heavily nested code. The JVM’s default stack size is rather small, so this can happen sooner than you might expect.

The stack size can be changed by passing -Xss... at JVM startup, for example -Xss16M. How to do this depends on what IDE and/or build tool you are using. For sbt, add it to .jvmopts.

If the stack overflow doesn’t go away no matter how much stack you give the compiler, then it’s a compiler bug. Please report it on the Scala 2 bug tracker or Scala 3 bug tracker, but check first if it’s a duplicate of an existing ticket.

I set a setting in sbt but nothing happened. Why?

There could be a lot of reasons. An extremely common one, that almost everyone runs into sooner or later, is that you have a bare setting in a multi-project build.

For example, if you add this to your build.sbt:

scalaVersion := "2.13.14"

that’s a “bare” setting, and you might expect it to apply build-wide. But it doesn’t. It only applies to the root project.

In many cases one should instead write:

ThisBuild / scalaVersion := "2.13.14"

Other possibilities include:

  • the common settings pattern, where you put shared settings in a val, typically named commonSettings, and then .settings(commonSettings) in every project you want to apply to them to.
  • in interactive usage only, set every

Here’s some further reading:

Contributors to this page: