Published 2013-12-21.
Last modified 2024-07-18.
Time to read: 6 minutes.
This lecture continues our exploration of simple Scala programs. Looping constructs and other control statements are also discussed.
Exploring Scala with the REPL

The REPL is useful for interactively experimenting with an incantation before you write some code. This is a much more productive way of working than the edit / compile / debug loop that you would otherwise have to perform.
Literals
Scala supports literals for integer numbers, floating point numbers, characters, booleans, symbols, and strings. The syntax for Scala literals is similar to Java literals.
Integers
Values of type Int
are all integer numbers between −231−231 and
231−1231−1, inclusive.
Values of type Long
are all integer numbers between −263−263 and
263−1263−1, inclusive.
A compile-time error occurs if an integer literal denotes a number outside these ranges.
Integer literals are usually of type Int
, or of type Long
when followed by a
L
or l
suffix.
(Lowercase l
is deprecated for reasons of legibility.)
The numeric ranges given by these types are:
Byte −27 to 27−1
Short −215 to 215−1
Char 0 to 216−1
The digits of a numeric literal may be separated by arbitrarily many underscores for purposes of legibility.
0
21_000
0x7F
-42L
0xFFFF_FFFF
Let’s create some integer variables using the Scala REPL:
scala> 5+2 res0: Int = 7
scala> val zero = 0 zero: Int = 0
scala> 5 * zero res1: Int = 0
scala> val zero: Int = 0 // redefining a variable is only possible in the REPL zero: Int = 0
Long Integers
As already mentioned, integer literals of type Long
are
denoted when followed by a L
suffix;
and values of type Long
are integer numbers between
−263−263 and 263−1263−1, inclusive.
scala> val zero = 0L // type Long is detected by the compiler zero: Long = 0
scala> val zero: Long = 0L // It is better to explicitly state all types zero: Long = 0
scala> val zero: Long = 0 // Automatic conversion from Int to Long zero: Long = 0
scala> 5 * zero // Multiplying an Int (5) with a Long (zero) returns a Long res2: Long = 0
scala> val zero: Int = 0L <console>:11: error: type mismatch; found : Long(0L) required: Int val zero: Int = 0L ^ scala> val long3: Int = -42L // Types must match when explictly stated ^ error: type mismatch; found : Long(-42L) required: Int
Hex Integers
Hex integers are denoted with a leading 0x
.
Hex digits are always interpreted as Int
.
scala> val x = 0x7F x: Int = 127
scala> val x: Int = 0xff // Case insensitive; 0xff and 0xFF produce the same value x: Int = 255
scala> val x: Int = 0x7F // Again, it is best to explicitly declare the types of all variables x: Int = 127
Two’s complement arithmetic is used, which means that a 32 bit value of all ones
(0xffffffff
) represents -1.
scala> val x = 0xffffffff x: Int = -1
scala> val hex1 = 0xFFFF_FFFF // The optional underscore makes the hex literal easier to read hex1: Int = -1
Larger values may not be specified using literal hex integers, even when cast to Long
.
scala> val x = 0x7ffffffff ^ error: integer number too large
scala> val x: Long = 0x7ffffffff ^ error: integer number too large
Underscores
The ability to embed underscores anywhere in a numeric literal was introduced in Scala 2.13. As you will see throughout this course and the next, Scala has many unrelated uses for underscores.
scala> 21_000 res3: Int = 21000
scala> val x21_2: Int = 21_000 x21_2: Int = 21000
scala> 2_1_0_0_0 + 1 res4: Int = 21001
scala> val x21_4: Int = 2_1_0_0_0 x21_4: Int = 21000
Floating Point
Floating point literals are of type Float
when followed by a floating point type
suffix F
or f
,
and are of type Double
otherwise.
The type Float
consists of all IEEE 754
32-bit single-precision binary floating point values,
whereas the type Double
consists of all IEEE 754 64-bit double-precision binary floating
point values.
If a floating point literal in a program is followed by a token starting with a letter, there must be at least one intervening whitespace character between the two tokens.
0.0 1e30f
3.14159f 1.0e-100 .1
scala> val x = 0.0 // The default floating point type is Double x: Double = 0.0
scala> val x: Double = 0.0 // Again, best to to declare all types x: Double = 0.0
scala> val x = 1e30f // The f specifier indicates type Float x: Float = 1.0E30
scala> val x: Double = 1e30f // Upcast from Float to Double by specifying the type x: Double = 1.0000000150474662E30
scala> val x = 1.0e-100 x: Double = 1.0E-100
Boolean
Values for type Boolean
are true
and false
.
scala> val b = true b: Boolean = true
scala> val b = false b: Boolean = false
scala> val b: Boolean = false // Again, it is best to explicitly declare the type of every variable b: Boolean = false
String
A string literal is a sequence of characters in double quotes.
The characters can be any Unicode character except the double quote delimiter or \u000A
(LF
) or \u000D
(CR
);
or any Unicode character represented by either a Unicode escape or by an escape sequence.
If the string literal contains a double quote character,
it must be escaped using "\""
.
The value of a string literal is an instance of class String
.
Here are examples:
scala> "Hello,world!\n" res0: String = "Hello, world!"
scala> "\"Hello,\" replied the world." res1: String = ""Hello," replied the world."
Character
A character literal is a single character enclosed in quotes.
The character can be any Unicode character except the single quote delimiter or \u000A
(LF
) or \u000D
(CR
);
or any Unicode character represented by either a Unicode escape or by an escape sequence.
’a’
’\u0041’ ’\n’ ’\t’
Note that although Unicode conversion is done early during parsing,
so that Unicode characters are generally equivalent to their escaped expansion in the source text,
literal parsing accepts arbitrary Unicode escapes, including the character literal
’\u000A’
, which can also be written using the escape sequence
’\n’
.
Some examples in the REPL:
scala> val x = ’a’ x: Char = a
scala> println(x) a
scala> val x = ’\u0041’ x: Char = A
scala> val x: Char = ’\u0041’ // Again, specify all types! x: Char = A
You can add Char
s together to yield another Char
.
Sometimes this is what you didn’t mean, so take care:
scala> println(’\u0041’ + ’\t’ + ’x’) // Error: This does not concatenate 3 Chars into a String 194
scala> println(’\u0041’.toString + ’\t’.toString + ’x’.toString) // This produces a String with 3 characters A x
Ranges
Let’s explore how to define a
Range
of integers containing values from 1 to three, inclusive.
Note that the REPL stores the result in an automatically named variable called
res0
, of type scala.collection.immutable.Range.Inclusive
:
scala> 1 to 3 res0: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
The range above was written with infix notation.
This is possible because to
is actually a method that takes a single parameter.
Any method which takes a single parameter can be written with infix notation.
We could have written the statement with dot notation to get the same effect:
scala> 1.to(3) res2: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
The above seems like the 1
, an Int
value object,
has a method called to
that accepts the argument 3
.
In fact, this is not actually true – instead,
the Int
type has been enriched with a
variety of methods
through the use of predefined implicits.
The next course
(Intermediate Scala)
teaches you how to enrich classes through the use of implicits.
We could also do away with the syntactic sugar, and write the same range as follows. Note that this is not any more efficient, and is harder to read:
scala> scala.collection.immutable.Range.inclusive(1, 3) res3: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
We could shorten the previous incantation using an import
statement to import the Range
class.
scala> import scala.collection.immutable.Range import scala.collection.immutable.Range
scala> Range.inclusive(1, 3) res4: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
We can also import the inclusive
method from
the Range
class.
You can use the tab key to complete package and variable names.
scala> import scala.collection.immutable.Range.inclusive import scala.collection.immutable.Range.inclusive
scala> inclusive(1, 3) res5: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3)
... and we can import all methods from a class:
scala> import scala.collection.immutable.Range._ import scala.collection.immutable.Range._
Now let’s use the range to print out
"Hello, world!
" three times:
scala> 1 to 3 foreach { i => println("Hello, world!") } Hello, world! Hello, world! Hello, world!
Notice that the Scala expression parsed from left to right, so the range is computed before the foreach
is executed.
In other words, the above is equivalent to:
scala> (1 to 3) foreach { i => println("Hello, world!") } Hello, world! Hello, world! Hello, world!
Again, the above was written with infix notation.
We could rewrite it using postfix notation
(note the period between the range and foreach
).
scala> (1 to 3).foreach { i => println("Hello, world!") } Hello, world! Hello, world! Hello, world!
The above is also equivalent to:
scala> Range.inclusive(1, 3).foreach { i => println("Hello, world!") } Hello, world! Hello, world! Hello, world!
Because all the methods of Range
were included,
we could also write this as:
scala> inclusive(1, 3).foreach { i => println("Hello, world!") } Hello, world! Hello, world! Hello, world!
Now let’s display the value of i
for each iteration of the loop:
scala> 1 to 3 foreach { i => println("Hello, world #" + i) } Hello, world #1 Hello, world #2 Hello, world #3
Here is a more convenient way of writing the same thing.
The current instance of the val i
is substituted for
$i
in the string because string interpolation is enabled for
strings that are prefaced with the letter s
.
scala> 1 to 3 foreach { i => println(s"Hello, world #$i") } Hello, world #1 Hello, world #2 Hello, world #3
Range
s are lazily computed.
We will discuss what that means in the
Immutable Collections and
Memoization in Depth
lectures of the
Intermediate Scala course.
until and the indices Idiom
The to
operator iterates up to and including the last value.
However, when you want to iterate over a collection using indices,
which are zero-based,
you need to use the exclusive Range
returned by until
instead of the inclusive Range
returned by to
.
scala> 0 to 3 res6: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> 0 until 3 res7: scala.collection.immutable.Range = Range(0, 1, 2)
Scala treats String
s as a collection of characters,
and you can reference any character of a String
by
providing the index of the desired character within parentheses:
scala> "abcdef"(3) res8: Char = d
scala> val string = "abcdef" string: String = abcdef
scala> string(2) res9: Char = c
Let’s access each character in string
and print it:
scala> string.length res10: Int = 6
scala> 0 until string.length res11: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5)
scala> 0 until string.length foreach { i => println(string(i)) } a b c d e f
Iterating over a collection using zero-based indices is such a common thing to
write that there is a shorthand idiom, indices
,
which generates the same exclusive Range
:
scala> string.indices res12: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5)
scala> string.indices foreach { i => println(string(i)) } a b c d e f
As another example, let’s create an immutable List
(we will discuss immutable List
s in detail in the
Immutable Collections lecture of the
Intermediate Scala course).
scala> val list = List("a", "b", "c") list: List[String] = List(a, b, c)
scala> 0 until list.length foreach { i => println(list(i)) } a b c
The indices
idiom works just the same for a List
as it does for String
:
scala> list.indices foreach { i => println(list(i)) } a b c
Other Scala Control Statements
Scala has three other control statements:
while
,
do while
and various types of for
statements.
while
while (condition) { expression(s) }
For example, we can write the previous example as:
var i = 1 while (i<=3) { println(s"Hello, world #$i") i = i + 1 }
Let’s try this in the REPL:
scala> var i = 1 i: Int = 1
scala> while (i<=3) { | println(s"Hello, world #$i") | i = i + 1 | } Hello, world #1 Hello, world #2 Hello, world #3
We could also add a semicolon after the println
so the entire while
statement can be expressed on a single line:
scala> var i = 1 i: Int = 1
scala> while (i<=3) { println(s"Hello, world #$i"); i = i + 1 } Hello, world #1 Hello, world #2 Hello, world #3
Scala assignment returns Unit
Scala assignment returns Unit
, unlike other languages like Java, where assignment returns the value assigned.
This means i = i + 1
cannot be used in a conditional expression:
while ((i = i + 1) <=3) println("THIS CODE WILL NOT COMPILE")
do while
do { expression(s) } while (condition)
Here is the same example written using do while
:
var i = 1 do { println(s"Hello, world #$i") i = i + 1 } while (i<=3)
Again, we will try this in the REPL, adding a semicolon after the println so the entire while statement can be expressed on a single line:
scala> var i = 1 i: Int = 1
scala> do { println(s"Hello, world #$i"); i = i + 1 } while (i<=3) Hello, world #1 Hello, world #2 Hello, world #3
for
For loops look a bit like for comprehensions, introduced later in this course.
The key difference is that for
loops do not contain the
yield
keyword, which will not be discussed in this course.
Formatting is optional; we could write this way:
for (i <- 1 to 3) println(s"Hello, world #$i")
Let’s look at this in the REPL:
scala> for (i <- 1 to 3) | println(s"Hello, world #$i") Hello, world #1 Hello, world #2 Hello, world #3
Or we could put it all on one line:
scala> for (i <- 1 to 3) println(s"Hello, world #$i") Hello, world #1 Hello, world #2 Hello, world #3
Exercise 2
Define a method that accepts a String
message and an Int
that
indicates the number of times to print it.
Test the method with a variety of input values.

Solution 2
Exercise 3
What gets printed out? Why?
for (i <- 1 to 3) { var i = 2 println(i) }

Solution 3
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.