Skip to content

Instantly share code, notes, and snippets.

@djspiewak
Last active November 15, 2024 14:38
Show Gist options
  • Save djspiewak/cb72c41ac335a3a9b28b3307be04aa43 to your computer and use it in GitHub Desktop.
Save djspiewak/cb72c41ac335a3a9b28b3307be04aa43 to your computer and use it in GitHub Desktop.

Getting Started in Scala

This is my attempt to give Scala newcomers a quick-and-easy rundown to the prerequisite steps they need to a) try Scala, and b) get a standard project up and running on their machine. I'm not going to talk about the language at all; there are plenty of better resources a google search away. This is just focused on the prerequisite tooling and machine setup. I will not be assuming you have any background in JVM languages. So if you're coming from Python, Ruby, JavaScript, Haskell, or anywhere…  I hope to present the information you need without assuming anything.

Disclaimer It has been over a decade since I was new to Scala, and when I was new to Scala, I was coming from a Java and Ruby background. This has probably caused me to unknowingly make some assumptions. Please feel free to call me out in comments/tweets!

One assumption I'm knowingly making is that you're on a Unix-like platform. Sorry, Windows users.

Getting the JVM

Everything we're going to do with Scala requires the JVM. Even if you ultimately intend to do in-browser development with Scala.js or run on the LLVM backend with Scala Native, you're still going to need the JVM just to run the Scala compiler. Fortunately, this is relatively straightforward.

The latest major version of the JVM (as of this writing) is 8 (sometimes referenced as "1.8" for legacy reasons). You can download it here (I believe that link is stable). At a minimum, you will need the JRE (Java Runtime Environment), but I recommend grabbing the JDK anyway. It's a somewhat larger download, but it comes baked with some goodies that you will find useful down the road.

Install the relevant JRE for your platform, and make sure that the java executable is available on your PATH. You can double-check that you have the appropriate version by running the following command:

$ java -version

You should see "1.8.somethingorother" Because reasons.

Trying Scala

At the present time, there is no great solution for trying out Scala in your browser without installing anything. There are a few implementations of the Scala Fiddle concept, and the one linked is (I think) the best. Because of technical limitations at present, the turnaround time is longer than one would like, and it's difficult to play around with libraries. You could also try scala-repl, which is a somewhat Mathematica-like environment in your browser, hosted as a local server instance.

I'm going to recommend the following pair of commands instead:

$ curl -L -o amm https://git.io/vP4Gw && chmod +x amm
$ ./amm

I'm a random person on the internet telling you to download a random URL and execute it. Please treat this with the appropriate suspicion! Here's what you're installing: Ammonite-REPL.

The results of this pair of commands will be a running Scala REPL with syntax coloring and reasonable error messages. For the most part, any Scala tutorial snippets you find on the internet should work in this environment. The exceptions are related to overloading, scoping, and class companions. But if you aren't doing anything related to those things, you should be fine. Here's a quick try-out:

@ println("Hello, World!") 
Hello, World!

To exit the REPL, type exit. Ctrl-C will kill a long-running expression (e.g. if you accidentally write an infinite loop).

The Ammonite REPL is generally better than the stock Scala REPL, so I recommend just hanging onto this executable. I make use of it on a daily basis!

Installing SBT

Ok, enough messing around. Let's get a real project up and running, using the same toolchain that nearly every Scala developer uses on a daily basis. We need to start by installing SBT.

SBT (Scala Build Tool) is the standard build system for Scala. It's a little bit like Maven, Gradle, Gems, or NPM; and as with all of those tools, it comes with its own quirks and weirdness. Fortunately, most of those quirks aren't going to bother you as you get started.

I recommend installing Paul Phillips' excellent sbt-extras script:

$ curl -L -o sbt https://raw.githubusercontent.com/paulp/sbt-extras/master/sbt && chmod +x sbt

SBT does have a standard script that is similar to PaulP's, but it's simply not as good. PaulP's script has some weirdness (particularly relating to some of the optional flags), but it generally does the job extremely well and it is very much the de facto standard SBT launcher script.

One of the things about Scala that is often very ill-explained is this: you don't download or install Scala. SBT will download, configure and cache the correct version of Scala for your project, along with all of its dependencies. Most Scala developers don't even have Scala installed outside of SBT!

Creating a Project

I would love it if I could say at this point "just run this one command and you're done!" But sadly, there's some more boilerplating we need to do.

The first step is to create your project's directory structure. I generally do something like this (for a project named funzles):

$ mkdir -p funzles/src/{main,test}/scala/funzles
$ cd funzles

This is generally followed by a git init, but we'll leave that for now. The src/main/scala/ directory convention comes from Maven, a build system and package manager for Java. It does have some advantages, but you're certainly going to have to get used to some very deeply nested directories! Generally speaking, you'll put your main project source files under src/main/scala/, while your tests are going to go in src/test/scala/. It is possible to organize your project files differently, but SBT understands this convention right out of the box, and other Scala developers will be very at home in your project if you stick to the standards.

Configuring Your Build

Now we need to configure SBT so it understands more about our project than the fact that we're using Scala. To do this, we need to create a file named build.sbt in the root directory of your project. For now, the following contents should be sufficient:

name := "funzles"

scalaVersion := "2.11.8"

At the time of this writing, 2.11.8 is the latest Scala version (with 2.12 in release candidate stage). You should replace this version string with whatever the latest Scala version is (the latest version is listed below the giant logo here).

A brief aside about SBT… SBT's configuration syntax (in .sbt files) is very extensive. There's a ton of stuff you can do with it. I do not recommend falling down that particular rabbit hole if you're new to Scala! If you decide to start doing more complex things, there are resources to help you do more with SBT (I recommend the book SBT In Action as well as the official SBT documentation pages).

Building and Running

Fortunately, we're all done with the boilerplate stuff! We can actually start doing real coding with a real project (sort of). Start by launching SBT (assuming you put the sbt script from earlier on your PATH):

$ sbt

In general, you're going to want to have SBT open in your project whenever you're doing development work. As you probably could see from running that command, SBT takes a bit of time to start (though much longer when it's your first time!). The SBT prompt offers several commands which are extremely useful, and keeping SBT itself open allows it to cache results and be significantly more efficient, reducing turnaround time on compilation and testing and increasing your productivity. Some quick commands to try:

  • compile – Compiles all of the main source files in your project. This task is incremental: if a file hasn't changed, and its dependent files have not changed, it will not be recompiled.
  • test – Compiles (if necessary) and runs all of the test source files in your project. Main source files will also be compiled if necessary.
    • test-quick – Compiles your main and test files (if necessary) and calculates which tests (relative to your last test run) have been affected by file changes. Only those tests are run. So the first time you run this command, it will run every test. The second time (if you make no file changes), no tests will be run. If you change some files, just the tests which touch those files will be rerun. I use this command a lot!
  • run – Compiles (if necessary) and runs the main class in your main source files. If there is no main class, you'll get an error. If there are multiple main classes, you'll be prompted to choose the one you want.
  • exit – Gets you out of Dodge (Ctrl-C also works!)
  • show <setting> – Prints out the value of the setting key specified by the setting parameter (without angle brackets). For example, show name should print out funzles.

Tab completion works, by the way! There are literally hundreds of available commands, of varying usefulness and specialization. Feel free to poke around. SBT doesn't have the ability to randomly break anything, and nothing you do in the SBT prompt (outside of the save command, which you should not use) will affect any of your source files. So it's safe to experiment!

Editing

There are Scala modes available for basically all of the major editors. There are also two major Scala IDEs (Integrated Development Environment) which provide richer language-aware features like content assist (i.e. "intellisense"), inline error reporting, debugging and more. I do not use an IDE when I'm doing Scala development; a text editor (like Emacs) works just fine. But if you prefer an IDE, the following options are recommended:

  • IntelliJ – This is more or less the gold standard for Scala IDEs. At least in my experience, almost everyone who uses a Scala IDE uses this one.
  • Eclipse – The Eclipse plugin is sponsored by Lightbend (who also sponsors most of the work on Scala itself). It is very good, and it is free, but it's somewhat less ubiquitous than IntelliJ in my experience.

If you (like me!) prefer to just stick with a plain old text editor, as I said, nearly all of them have very solid Scala modes. If you prefer to stick with a plain old text editor, you probably already have a strong preference as to the one you want to stick with, but just to keep you informed… The following editors have particularly good Scala modes, listed in order of quality:

  • Emacs – I'm not an Emacs user, but honestly the Emacs Scala mode is second to none. The many contributors over the years have simply done a superb job of making the language feel very much a first-class citizen in the editor.
  • Sublime 3 – This is my editor of choice, and several recent changes to the Scala mode have made it objectively one of the most comprehensive and accurate modes in existence (second only to Emacs). Note that Sublime 2 does not have the latest changes, and its Scala mode is proportionally less powerful.
  • Vim – Vim's Scala mode is a little bit behind. Depending on what version you acquire, you may or may not see support for things like macros or string interpolation. Additionally, there are some weird quirks with a few of the lesser-used corners of the language (such as pattern guards). But it does the job and it does it quite well.
  • Atom – Atom is basically solid at everything it does, and Scala is no exception. The original version of Atom's Scala mode appears to have been based on the Sublime 2 Scala mode, and shares many of its flaws, but it gets the job done.
  • TextMate – I can't speak to this mode too specifically, but I know that several of the Sublime 3 Scala mode improvements have been backported to recent TextMate builds. I am not aware if the latest stable TextMate has these changes.
  • jEdit – The Scala mode is excellent and has consistently accurate syntax highlighting and auto-indentation. There are some limitations though, and syntax highlighting may not work quite as well if you format your Scala code using a non-standard style.

As another sidebar, there exists a middle-ground project between a full IDE like IntelliJ and a raw text editor like Emacs. That middle ground is ENSIME. Very much inspired by the SLIME project for Emacs, ENSIME is a subprocess which provides many IDE-like features inside the context of a basic text editor. Several editors are supported, but Emacs is the most stable and full-featured by far.

Creating, Compiling and Running

Use your editor of choice to create a file in the src/main/scala/funzles/ directory with the following contents (the name of the file isn't significant, though it must use the .scala extension):

package funzles

object Fun {
  def main(args: Array[String]): Unit = {
    println("Hello, World!")
  }
}

From within the SBT prompt, run the following command (you can also run sbt run from your shell prompt, but again, you will pay the startup penalty every time):

> run

SBT will compile and run your Fun class, printing Hello, World! to standard output.

One very useful trick of SBT is the ~ prefix. You can prepend a ~ to any SBT command. The result of this prefix is the command will run once, followed by SBT pausing and monitoring your project files. Whenever your source files change, it will immediately re-run the command, followed by another pause to monitor files for subsequent runs. This will continue until you break out of the ~ by using Enter. For example, run the following command:

> ~run

Now go back to your editor, and add the following line to the main method:

// ...
println("...do you read me?")

By the time you tab back to your terminal application, your class should have been recompiled and rerun, with the results waiting for you.

Once you get ramped up in Scala, you will find yourself using ~ almost all the time in SBT. It is particularly useful in conjunction with the test-quick command referenced earlier.

Depending on Libraries

Before we close out, it's worth noting briefly how it is you can depend upon third-party libraries. The JVM has a very extensive ecosystem of libraries, built up over more than 20 years of community development. Scala can trivially access any Java library, and SBT is very much aware of the Java ecosystem.

Let's say that you want to do some low-level asynchronous network IO using the fantastic Netty framework. You will want to look for the latest version at search.maven.org. After a bit of digging, it looks like the latest Netty artifact (at the time of this writing) is here. Specifically, the full artifact descriptor is io.netty:netty-all:4.1.6.Final. We can instruct SBT to make this framework available to our project by modifying our build.sbt file:

name := "funzles"

scalaVersion := "2.11.8"

libraryDependencies += "io.netty" % "netty-all" % "4.1.6.Final"

If you still have the SBT prompt open (which you should!), run the reload command. This will cause SBT to pick up the latest changes to the build.sbt file. Now that you've done this, you can use Netty within your project sources as described in their documentation.

Now, Netty is a Java framework. Scala frameworks can be added to our project using much the same mechanism, but the syntax and process is a little different. Let's imagine that we want to add a library for doing abstracted functional programming, similar to what we would get in Haskell out of the box. After a bit of googling, we might find that Cats is one such project. Visiting the project page on GitHub, we see early on in the README the following incantation (as of this writing):

libraryDependencies += "org.typelevel" %% "cats" % "0.7.2"

So all we need to do is add that to our build.sbt file, run another reload and we should be good to go!

name := "funzles"

scalaVersion := "2.11.8"

libraryDependencies += "io.netty" % "netty-all" % "4.1.6.Final"
libraryDependencies += "org.typelevel" %% "cats" % "0.7.2"

Most libraries written in Scala will have a line like this in their README, which makes it quite easy to add almost any Scala library to an SBT build without messing around at search.maven.org.

One thing you will notice is that this dependency uses two percent signs (%) rather than just the one that we used with Netty. Without going into too much detail, this is part of SBT's workaround mechanism for the fact that binary compatibility in Scala can be a hard problem. As a general rule, if you're depending on a Java library, just use one %. If you're depending on a Scala library, use two.

Testing

Testing is incredibly important in all languages, which is why I'm not going to spend any time on it at all! :-) More seriously, Scala has two standard testing frameworks (with a third standard support framework used by both), and nearly code written in the language is tested using one of these two:

  • ScalaTest – A very broad test framework offering support for several testing paradigms (JUnit-style unit testing, RSpec-style BDD, and everything in between). ScalaTest supports a very large number of test definition styles, selected by the trait you inherit (e.g. FunSpec).
  • Specs2 – A slightly more narrowly-focused test framework which focuses on BDD. Specs2 supports two different test definition styles: mutable and immutable. I highly recommend sticking with the mutable definition style, as it is more straightforward and far more commonly used in the Scala ecosystem.

I personally prefer Specs2, but frankly both frameworks provide nearly the same general functionality. Be warned that Specs2's documentation and most of its examples generally focuses on the immutable API, which as I mentioned, is less conventional. Partially for this reason, ScalaTest has significantly better documentation for test definition and structure, while Specs2 has significantly better documentation for its assertion functionality (matchers).

Next Steps

You're now up and running with a fully-functional, no-holds-barred Scala project environment. All the training wheels are off here: this is literally the same sort of environment (build setup, filesystem and editor) that nearly all Scala developers use on a daily basis! So where do you go from here?

My recommendation would be to continue working through the many excellent Scala learning resources. Coursera has some very good formal courses. There are several books. You can find an endless number of tutorials online spanning all knowledge levels. Twitter, IRC and Gitter are all excellent resources, and you will find many members of the Scala community willing and eager to help you. Get out there and make something awesome!


Dual licensed under CC BY 4.0/CC BY 3.0

@csaltos
Copy link

csaltos commented Oct 17, 2016

Excellent !!

@MaggieLeber
Copy link

MaggieLeber commented Oct 17, 2016

Just a suggestion: despite diligent efforts by several people, I have not yet seen Ammonite work correctly on Windows, even in Cygwin. Maybe I should try it again...but considering that a surprising number of people will try this on Windows machines a note might be in order.

@mtk
Copy link

mtk commented Oct 17, 2016

i've found this useful in a rapidly evolving library ecosystem: https://github.com/rtimush/sbt-updates

@joaosa
Copy link

joaosa commented Oct 18, 2016

Really good intro :)

@jadeallenx
Copy link

As a Scala noob who went through a lot of this the Hard Way, I hope this gets the publicity it deserves. It's super not obvious what the generally accepted practices are for starting projects (directories, tooling, etc.)

It would be helpful if you could expand the discussion of editors a little bit further - for example, recommending common plugins and their configurations as appropriate.

@jadeallenx
Copy link

jadeallenx commented Oct 19, 2016

I would really really like to encourage you to contribute this guide to How I Start - Scala is a notable absence and this would be perfect!

@yawaramin
Copy link

Daniel, this is awesome. As far as I'm concerned, this is the content we need on the Scala Getting Started page.

@felipeeflores
Copy link

Pretty cool I wish I had these a few years ago! Good work

@sjrd
Copy link

sjrd commented Oct 20, 2016

Very nice!

A few comments:

Configuring Your Build

I strongly recommend to make the reader create a project/build.properties file as well. This omission is a common mistake made by beginners and experts alike.

test-quick

test-quick is obsolete syntax. Since 0.13.0 the canonical name is testQuick. All tasks and settings are now consistently camelCase in the .sbt files and in the prompt.

(the name of the file isn't significant, though it must use the .scala extension)

It is true that it is not significant, but it would be worth pointing out the the common practice is to give it the same name as the (main) class in the file. Relatedly, maybe point out that it's in src/main/scala/fuzzle/ because it's the name of the package?

@lshoo
Copy link

lshoo commented Oct 25, 2016

Real awesome!
There are too luck to learn scala now!

@ches
Copy link

ches commented Nov 14, 2016

A few thoughts for keeping the living document in vogue:

  • Use the new sbt new for the "Creating a Project" section, with a simple template like sbt new scala/scala-seed.g8. This covers @sjrd's project/build.properties suggestion, albeit implicitly. Though it is also nice to know how simple it is without any such magic needed (you don't even need any build.sbt at all, technically).
  • Reference Scaladex as an analog to search.maven.org for the "Depending on Libraries" section. It gives copy-and-paste-ready coordinates syntax for sbt, Ammonite REPL, etc. (plus Scaladoc links and such).

@djspiewak
Copy link
Author

Going to make some updates here soon. The advent of sbt new is quite significant, and it does short-circuit some of these steps. Also, I went back and forth a ton about the build.properties point, since @sjrd is absolutely correct that it's important, but I didn't want to over-burden newcomers. I think sbt new probably obviates the question altogether.

I'm sort of torn on scaladex. In practice, I don't really find it any more helpful than just jumping to the github project pages, but then I haven't actively pushed myself to use it in anger yet. I'm going to be a coward and punt on that until a later date, but keeping it in mind for future updates.

@nandosola
Copy link

Nice work! We're going to use this for an introductory short workshop at @MalagaScala, with real newbies. I'll get their feedback, and provide ours as well. Thanks for this!

@dadepo
Copy link

dadepo commented Nov 28, 2016

Thanks for this. Just one observation though. Quoting what you wrote:

One of the things about Scala that is often very ill-explained is this: you don't download or install Scala. SBT will download, configure and cache the correct version of Scala for your project, along with all of its dependencies. Most Scala developers don't even have Scala installed outside of SBT!

But yet on the official site here: http://scala-lang.org/download/install.html, there is instruction on how to download and install Scala binaries.

Can you be kind to expound on the "you don't download or install Scala" bit in that paragraph? Especially when it says do download and install on the official site. By expound I mean to explain how "things" still work if scala is not downloaded, and how downloading Scala (as recommended) differs from using just sbt.

@Chabane
Copy link

Chabane commented Oct 2, 2017

thanks @djspiewak!

and how to generate a jar? Do I need to have a Build.scala file?

@ychakiris
Copy link

This is SUPER helpful. Thanks for a great job!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment