Scala

Scala is a hybrid language that supports both object-oriented and functional styles of programming. It was invented by Martin Odersky.

Scala programs are compiled into java class files, and run on the Java virtual machine. A Scala program can use Java classes, including the many built-in classes that ship with the JVM.

Scala is statically-typed, meaning that each variable and value has a data type that is known at compile time. Java is also statically typed. Unlike Java, Scala programs do not need to specify types explicitly in situations where a type can be inferred automatically. This makes Scala programs significantly more concise than Java programs.

Functional programming

Functional programming is a programming style characterized by:

One way to understand what is meant by "immutable variables and data structures" and "no side-effects" is to think about what it would be like to program in a language in which there was no assignment operator. Each variable in the program would have an initial value, but that value could not be changed.

Functional programming has two advantages over imperative programming (where variables and data structures are mutable):

There are some disadvantages of functional programming:

Scala is not a pure functional language, since it does support mutable data. This allows the programmer to use both functional and imperative styles where they make the most sense.

Scala data types

Scala has many of the same fundamental of data types as Ruby:

See textbook for details and syntax.

Scala supports code blocks that are very similar to those supported by Ruby. For example, ranges and lists have methods such as foreach, count, and map that allow a sequence of values to be transformed with a code block.

Example: computing a factorial by multiplying a series of integers:

(1 to 6).reduceLeft( (a, b) => a * b )

(1 to 6) is an inclusive range. The reduceLeft method is very similar to Ruby's inject method: it starts by applying the code block to the first two values in the range, and then continues applying the previously computed value to the next value in the range.

Scala classes

Scala classes are like Java classes: they define a data type where the values are objects with fields and methods.

Scala classes use a much more compact syntax than Java classes. In particular, a Scala class definition defines

all in one. For example:

class SuperHero(name : String, hates : List[String], canBeat : List[String]) {
    def getName : String = name

<span class="k">def</span> <span class="n">hates</span><span class="o">(</span><span class="n">other</span> <span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">:</span> <span class="kt">Boolean</span> <span class="o">=</span> <span class="n">hates</span><span class="o">.</span><span class="n">contains</span><span class="o">(</span><span class="n">other</span><span class="o">)</span>

<span class="k">def</span> <span class="n">canBeat</span><span class="o">(</span><span class="n">other</span> <span class="k">:</span> <span class="kt">String</span><span class="o">)</span> <span class="k">:</span> <span class="kt">Boolean</span> <span class="o">=</span> <span class="n">canBeat</span><span class="o">.</span><span class="n">contains</span><span class="o">(</span><span class="n">other</span><span class="o">)</span>

}

An instance of the SuperHero class has three fields: name, hates, and canBeat, and that the SuperHero class's constructor requires values for each of these fields as parameters. This eliminates a significant amount of redundancy that would occur in a Java program. Here is the equivalent Java class:

public class SuperHero {
    private String name;
    private List<String> hates;
    private List<String> canBeat;

<span class="kd">public</span> <span class="nf">SuperHero</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="n">hates</span><span class="o">,</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">String</span><span class="o">&gt;</span> <span class="n">canBeat</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">hates</span> <span class="o">=</span> <span class="n">hates</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">canBeat</span> <span class="o">=</span> <span class="n">canBeat</span><span class="o">;</span>
<span class="o">}</span>

<span class="kd">public</span> <span class="n">String</span> <span class="nf">getName</span><span class="o">()</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">name</span><span class="o">;</span>
<span class="o">}</span>

<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">hates</span><span class="o">(</span><span class="n">String</span> <span class="n">other</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">hates</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="n">other</span><span class="o">);</span>
<span class="o">}</span>

<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">canBeat</span><span class="o">(</span><span class="n">String</span> <span class="n">other</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">return</span> <span class="n">canBeat</span><span class="o">.</span><span class="na">contains</span><span class="o">(</span><span class="n">other</span><span class="o">);</span>
<span class="o">}</span>

}

Notice that to define an initialize the name field, the identifier name appears in four different places!

Scala objects can be created and used in much the same way as Java objects:

object SuperHeroTest {
    def main(args: Array[String]) {
        // Create some SuperHeros
        val particleMan = new SuperHero("Particle Man", List(), List())
        val personMan = new SuperHero("Person Man", List(), List())

    <span class="k">val</span> <span class="n">triangleMan</span> <span class="k">=</span> <span class="k">new</span> <span class="nc">SuperHero</span><span class="o">(</span>
        <span class="s">"Triangle Man"</span><span class="o">,</span>
        <span class="nc">List</span><span class="o">(</span><span class="s">"Particle Man"</span><span class="o">,</span> <span class="s">"Person Man"</span><span class="o">),</span>
        <span class="nc">List</span><span class="o">(</span><span class="s">"Particle Man"</span><span class="o">,</span> <span class="s">"Person Man"</span><span class="o">))</span>

    <span class="c1">// Triangle Man hates Person Man

println(triangleMan.hates(particleMan.getName))

    <span class="c1">// They have a fight: Triangle wins

println(triangleMan.canBeat(particleMan.getName)) } }

Note that SuperHeroTest is an object, not a class. Essentially, SuperHeroTest is a data type that has only one instance. Only Scala object types can define a main method.

A complete example

The first section of the textbook suggests evaluating Tic Tac Toe boards as a self-test exercise.

To represent the board, we will use a list of list of Char values, which is the list of rows in the board. This type is written List[List[Char]]. A Board object is constructed from the list of lists. Here is the class definition / main constructor:

class Board(rows : List[List[Char]]) {

A Board object has just one field, rows.

The Board class has methods which query the board to determine if a particular piece ('X' or 'O') has won. Checking for a winner involves checking the rows, columns, and diagonals, to see if one of them has all three values set to the same value as the piece we're checking.

We can simplify our win-checking code by creating a method that checks an arbitrary list of characters to see if the first three members are equal to a specified piece value:

def win(seq : List[Char], piece : Char) : Boolean = {
  seq.count( c => c == piece ) == 3
}

Note that the count method of List executes an arbitrary code block on each member of the list, and counts the number of times the code block returns a true value.

Given the win method, checking all rows of the board is easy:

rows.count( r => win(r, piece) ) > 0

Again, we use the count method, this time to check whether the win method reported a true result for at least one row of the board.

Checking columns is slightly more complicated, since the board is stored as rows. We introduce a method called column which, given the index of a column (0-2), returns a list of characters representing that column:

def column(index : Int) : List[Char] = {
  rows.map( r => r(index) )
}

The map method of List applies a code block to the sequence of values in the list, and returns a list containing the results. In the column method, we map a block which selects, for each row, the member of the row whose index is index. (Note that Scala uses parantheses instead of square brackets to access an element of a List.)

Now that we have a method that returns a column, it is easy to check columns:

(0 until 3).count( i => win(column(i), piece) ) > 0

Here, the count method is used on the range 0 until 3 to count the number of columns where the win method returns true.

Diagonals require some thought to handle. Here is a method called diag that returns a List of characters representing one of the board's diagonals. The starting column and row are specified, as well as the column and row increments needed to generate the other column/row locations in the diagonal:

def diag(x : Int, y : Int, dx : Int, dy : Int) : List[Char] = {
  (0 until 3).map( i => rows(y + idy)(x + idx) ).toList
}

In a way that is similar to the column method, the diag method uses a range to generate all three column/row pairs for the diagonal, and uses map to generate a list containing the characters in the diagonal. The diagonals are checked for a winning configuration using the code:

win(diag(0, 0, 1, 1), piece) ||
win(diag(2, 0, -1, 1), piece)

In other words, check the upper-left to lower-right diagonal and the upper-right to lower-left diagonal.

Here is the entire Board class:

class Board(rows : List[List[Char]]) {
    def isWinner(piece : Char) : Boolean = {
      rows.count( r => win(r, piece) ) > 0 ||
        (0 until 3).count( i => win(column(i), piece) ) > 0 ||
        win(diag(0, 0, 1, 1), piece) ||
        win(diag(2, 0, -1, 1), piece)
    }

<span class="k">def</span> <span class="n">column</span><span class="o">(</span><span class="n">index</span> <span class="k">:</span> <span class="kt">Int</span><span class="o">)</span> <span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Char</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
  <span class="n">rows</span><span class="o">.</span><span class="n">map</span><span class="o">(</span> <span class="n">r</span> <span class="k">=&gt;</span> <span class="n">r</span><span class="o">(</span><span class="n">index</span><span class="o">)</span> <span class="o">)</span>
<span class="o">}</span>

<span class="k">def</span> <span class="n">diag</span><span class="o">(</span><span class="n">x</span> <span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">y</span> <span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">dx</span> <span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">dy</span> <span class="k">:</span> <span class="kt">Int</span><span class="o">)</span> <span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Char</span><span class="o">]</span> <span class="k">=</span> <span class="o">{</span>
  <span class="o">(</span><span class="mi">0</span> <span class="n">until</span> <span class="mi">3</span><span class="o">).</span><span class="n">map</span><span class="o">(</span> <span class="n">i</span> <span class="k">=&gt;</span> <span class="n">rows</span><span class="o">(</span><span class="n">y</span> <span class="o">+</span> <span class="n">i</span><span class="o">*</span><span class="n">dy</span><span class="o">)(</span><span class="n">x</span> <span class="o">+</span> <span class="n">i</span><span class="o">*</span><span class="n">dx</span><span class="o">)</span> <span class="o">).</span><span class="n">toList</span>
<span class="o">}</span>

<span class="k">def</span> <span class="n">win</span><span class="o">(</span><span class="n">seq</span> <span class="k">:</span> <span class="kt">List</span><span class="o">[</span><span class="kt">Char</span><span class="o">],</span> <span class="n">piece</span> <span class="k">:</span> <span class="kt">Char</span><span class="o">)</span> <span class="k">:</span> <span class="kt">Boolean</span> <span class="o">=</span> <span class="o">{</span>
  <span class="n">seq</span><span class="o">.</span><span class="n">count</span><span class="o">(</span> <span class="n">c</span> <span class="k">=&gt;</span> <span class="n">c</span> <span class="o">==</span> <span class="n">piece</span> <span class="o">)</span> <span class="o">==</span> <span class="mi">3</span>
<span class="o">}</span>

}

This is a remarkably compact piece of code, especially compared to the equivalent Java code, which would probably require 2 or 3 times more lines of code.