Getting started with the Scala REPL (command-line shell)

This is an excerpt from the Scala Cookbook. This is Recipe 14.1, “How to get started with the Scala REPL.”

Problem

You want to get started using the Scala REPL (“Read-Evaluate-Print-Loop”) command line interpreter, including understanding some of its basic features, such as tab completion, starting the REPL with different options, and dealing with errors.

Solution

To start the Scala REPL, type scala at your operating system command line:

$ scala

You’ll see a welcome message and Scala prompt:

Welcome to Scala version 2.10.0
Type in expressions to have them evaluated.
Type :help for more information.

scala> _
Welcome, you’re now using the Scala REPL.

Inside the REPL environment, you can try all sorts of different experiments and expressions:

scala> val x, y = 1
x: Int = 1
y: Int = 1

scala> x + y
res0: Int = 2

scala> val a = Array(1, 2, 3)
a: Array[Int] = Array(1, 2, 3)

scala> a.sum
res1: Int = 6

As shown in the second example, if you don’t assign the result of an expression to a variable, the REPL creates its own variable, beginning with res0, then res1, etc. You can use these variable names just as though you had created them yourself:

scala> res1.getClass
res2: Class[Int] = int

Writing tests like this in the REPL is a great way to run experiments outside of your IDE or editor.

There are a few simple tricks that can make using the REPL more effective. One trick is to use tab completion to see the methods that are available on an object. To see how tab completion works, create a String object, type a decimal, and then press the Tab key. With Scala 2.10, the REPL shows that more than 30 methods are available on a String instance:

scala> "foo".[Tab]
+                  asInstanceOf      charAt       codePointAt           "
codePointBefore    codePointCount    compareTo
// a total of thirty methods listed here ...

If you press the Tab key again, the REPL expands the list to more than 50 methods:

scala> "foo".[Tab][Tab]
// 51 methods now listed ...

Similarly, the Int object expands from 25 to 34 methods when you press the Tab key twice.

When you press the Tab key the first time, the REPL filters out many common methods, but by pressing the Tab key the second time, it removes those filters and increases the verbosity of its output. You can find an explanation of how this works at the JLineCompletion class link in the See Also section of this recipe.

You can also limit the list of methods that are displayed by typing the first part of a method name and then pressing the Tab key. For instance, if you know that you’re interested in the to* methods on a Scala List, type a decimal and the characters to after a List instance, and then press Tab:

scala> List(1,2,3).to[Tab]
toByte  toChar  toDouble  toFloat  toInt  toLong  toShort  toString

These are all the List methods that begin with the letters to.

Although the REPL tab-completion feature is good, it currently doesn’t show methods that are available to an object that results from implicit conversions. For instance, when you invoke the tab-completion feature on a String instance, the REPL doesn’t show the methods that are available to the String that come from the implicit conversions defined in the StringOps class. To see methods available from the StringOps class, you currently have to do something like this:

scala> val s = new collection.immutable.StringOps("")
s: scala.collection.immutable.StringOps = s

scala> s.[Tab]

After pressing the Tab key, you’ll see dozens of additional methods that are available to a String object, such as all the to* and collection methods.

The REPL also doesn’t show method signatures. Hopefully features like this will be added to future versions of the REPL. In the meantime, these are most easily seen in an IDE.

Discussion

I use the REPL to create many small experiments, and it also helps me understand some type conversions that Scala performs automatically. For instance, when I first started working with Scala and typed the following code into the REPL, I didn’t know what type the variable x was:

scala> val x = (3, "Three", 3.0)
x: (Int, java.lang.String, Double) = (3,Three,3.0)

With the REPL, it’s easy to run tests like this, and then call getClass on a variable to see its type:

scala> x.getClass
res0: java.lang.Class[_ <: (Int, java.lang.String, Double)] = class scala.Tuple3

Although some of that result line is hard to read when you first start working with Scala, the text on the right side of the = lets you know that the type is a Tuple3. Though this is a simple example, when you’re working with more complicated code or a new library, you’ll find yourself running many small tests like this in the REPL.

A Tuple3 is a specific instance of a tuple. A tuple is a container for heterogeneous objects. A Tuple3 is simply a tuple that contains three elements. Here’s a Tuple2 that holds a String and a Char:

scala> val y = ("Foo", 'a')
y: (java.lang.String, Char) = (Foo,a)

scala> y.getClass
res1: java.lang.Class[_ <: (java.lang.String, Char)] = class scala.Tuple2

See Recipe 10.27, “Tuples, for When You Just Need a Bag of Things” for more information.

REPL command-line options

If you need to set Java properties when starting the Scala interpreter, you can do so like this on Unix systems:

$ env JAVA_OPTS="-Xmx512M -Xms64M" scala

That command sets the maximum and initial size of the Java memory allocation pool. You can confirm this by looking at the maximum available memory in the REPL:

scala> Runtime.getRuntime.maxMemory / 1024
res0: Long = 520064

When starting the Scala 2.10 REPL without any options, the same command yields a different result:

scala> Runtime.getRuntime.maxMemory / 1024
res0: Long = 258880

You can also use the -J command-line argument to set parameters. I ran into a java.lang.OutOfMemoryError in the REPL while processing a large XML dataset, and fixed the problem by starting the REPL with this command:

$ scala -J-Xms256m -J-Xmx512m

The scala command you’re running in these examples is actually a shell script, so if you need to modify these parameters permanently, just edit that script. (On Unix systems, you can also create a wrapper script or an alias.)

Deprecation and feature warnings

From time to time, you may see a message that suggests starting the REPL with the -deprecation or -feature option enabled. For instance, attempting to create an octal value by entering an integer value with a leading zero generates a deprecation warning:

scala> 012
warning: there were 1 deprecation warnings; re-run with -deprecation for details
res0: Int = 10

To see the error, you could restart the REPL with the -deprecation option, like this:

$ scala -deprecation

Fortunately, restarting the REPL isn’t usually necessary. Beginning with Scala 2.10, it’s usually easier to ask the REPL to show the message with the :warning command:

scala> 012
warning: there were 1 deprecation warnings; re-run with -deprecation for details
res0: Int = 10

scala> :warning
<console>:8: warning: Treating numbers with a leading zero as octal is deprecated.
              012
              ^

The REPL documentation states that the :warning command shows “the suppressed warnings from the most recent line.”

If you run into the similar feature warning message, you can also issue the :warning command to see the error. If necessary, you can also restart the REPL with the -feature option:

$ scala -feature

The Scala Worksheet

If you’re using Eclipse with the Scala IDE plug-in, you can also run a REPL session in a Scala Console panel. Another alternative is to use the Scala Worksheet. The Worksheet is a plug-in that’s available for Eclipse and IntelliJ IDEA. It works like the REPL, but runs inside the IDE. Figure 14-2 shows what the Worksheet looks like in Eclipse.

Figure 14-2. The Scala Worksheet plug-in works like the REPL

See Also

  • Source code for the JLineCompletion class
  • The Tuple3 class