Some basic types

You can use stripMargin on strings. To use this method, put a pipe character (|) at the front of each line, and then call stripMargin on the whole string:

println("""|Welcome to Ultamix 3000.
           |Type "HELP" for help.""".stripMargin)


Welcome to Ultamix 3000.
Type "HELP" for help.

Symbol literals

A symbol literal is written 'ident, where ident can be any alphanumeric identifier. Such literals are mapped to instances of the predefined class scala.Symbol. Specifically, the literal 'cymbal will be expanded by the compiler to a factory method invocation: Symbol("cymbal").

Symbol literals are typically used in situations where you would use just an identifier in a dynamically typed language.

val s = 'aSymbol

Symbols are interned. If you write the same symbol literal twice, both expressions will refer to the exact same Symbol object.

String interpolation

val name = "reader"
println(s"Hello, $name!")
  • The expression, s"Hello, $name!" is a processed string literal.
  • the letter s immediately precedes the open quote
  • Scala will use the s string interpolator to process the literal.
  • The s interpolator will evaluate each embedded expression, invoke toString on each result, and replace the em- bedded expressions in the literal with those results.
  • string interpolation is implemented by rewriting code at compile time
  • The compiler will treat any expression consisting of an identifier followed immediately by the open double quote of a string literal as a string interpolator expression.

Operators anr methods

Scala has two other operator notations: prefix and postfix.

  • In prefix notation, you put the method name before the object on which you are invoking the method (for example, the ‘-’ in -7).
  • In postfix notation, you put the method after the object (for example, the “toLong” in “7 toLong”).

To see what operators you can use with Scala’s basic types, all you really need to do is look at the methods declared in the type’s classes in the Scala API documentation.

Arithmetic operations

val neg = 1 + -3
scala> -neg
res15: Int = 2

Relational and logical operations

The && and || operations short-circuit as in Java: expressions built from these operators are only evaluated as far as needed to determine the result. In other words, the right-hand side of && and || expressions won’t be evalu- ated if the left-hand side determines the result.

If you want to evaluate the right hand side no matter what, use & and | instead.

You may be wondering how short-circuiting can work given operators are just methods. Normally, all arguments are evaluated before entering a method, so how can a method avoid evaluating its second argument? The answer is that all Scala methods have a facility for delaying the evaluation of their arguments, or even declining to evaluate them at all.

Bitwise opeerations

Scala integer types also offer three shift methods: shift left (<<), shift right (>>), and unsigned shift right (>>>).

  • Shift left and unsigned shift right fill with zeroes as they shift.
  • Shift right fills with the highest bit (the sign bit) of the left-hand value as it shifts.
  • The leftmost bit in an integer type is the sign bit. If the leftmost bit is 1, the number is negative. If 0, the number is positive.

Object equality

== has been carefully crafted so that you get just the equality comparison you want in most cases.

First check the left side for null. If it is not null, call the equals method.

This kind of comparison will yield true on different objects, so long as their contents are the same and their equals method is written to be based on contents.

How Scala’s == differs from Java’s
In Java, you can use == to compare both primitive and reference types. On primitive types, Java’s == compares value equality, as in Scala. On reference types, however, Java’s == compares reference equality, which means the two variables point to the same object on the JVM’s heap. Scala provides a facility for comparing reference equality, as well, under the name eq. However, eq and its opposite, ne, only apply to objects that directly map to Java objects.

Operator precedence and associativity

a * b yields a.*(b), but a ::: b yields b.:::(a)

It is good style to use parentheses to clarify what operators are operating upon what expressions.


The main take-aways from this chapter are that operators in Scala are method calls, and that implicit conversions to rich variants exist for Scala’s basic types that add even more useful methods.