Short guide to Scala

Dedicated to Scala Johansson

What is Scala?

Scala is a scalable language based on Java. It adds functional programming features to the normal Java OO. One of the main advantages of Scala is that you can write shorter programs than in Java and still benefit from the many Java libraries out there. For instance this code in Java

1
2
3
4
5
6
7
class AClass {
      private String myString;
 
      public AClass(String string) {
          this.myString = string;
      }
  }

becomes

1
class AClass(myString: String)

As you can see semicolons are optional. Strangely enough Scala is statically typed. In fact the type system is pretty complex. I guess it is a matter of opinion whether this is good or bad.

Getting started

Variables

There are two types of variables that you can define val and var. A val represents a constant value and is final. A var can change.

1
val greeting = "Hi"

Notice that you don’t have to specify the type. This is called type inference, because greeting was initialized with a String literal, Scala figured out that greeting is of type String.

Functions

Functions are defined with def.

1
2
3
4
def min(i: Int, j: Int): Int = {
   if (i < j) x
      else j
}

This code is pretty self explanatory. All the Java types have an equivalent in Scala with similar name. The exception is void which matches Unit in Scala.

Tuples

Scala adds tupples to the Java collection classes. Tuples can contain different type of elements. In Java you would have to create a holder class for this data. The code below creates a tuple and prints its contents

1
2
3
val myTuple = (1, "Ivan")
println(myTuple._1)
println(myTuple._2)

Simple scripts

Here is a script that can display lines in a file or files like the cat command in Unix.

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh
exec scala "$0" "[email protected]"
!#
 
import scala.io.Source
 
if (args.length > 0) {
   for(arg <- args) {
      for (line <- Source.fromFile(arg).getLines)
         print(line)
      }
   }

You can run this as a shell script.

Pure OO

Scala classes cannot have static members. There are no primitives. Every value is an object. In Scala every method is an operator and vice versa. For instance we can define addition, multiplication and other operations for complex numbers.

1
2
3
4
5
6
7
8
9
10
11
12
class Complex(r : Double, i : Double) {
  var real = r
  val imaginary = i
  val modulus =  Math.sqrt(r * r + i * i)
  def +(that: Complex):Complex =
    new Complex(real + that.real, imaginary + that.imaginary)
  def -(that: Complex):Complex =
    new Complex(real - that.real, imaginary - that.imaginary)
  def * (that: Complex):Complex =
    new Complex(real * that.real - imaginary * that.imaginary,
      real * that.imaginary + imaginary * that.real)
}

and we can test it with JUnit or any other testing frameworks which is written in Java or Scala.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import org.junit._
 
class ComplexSuite {
    val one = new Complex(1.0, 0)
    val two = new Complex(2.0, 0)
 
    @Test
    def testAddition() {
      val sum = one + two
      Assert.assertEquals(sum.real, 3.0, 0.1)
      Assert.assertEquals(sum.imaginary, 0, 0.1)
    }
 
    @Test
    def testSubtraction() {
      val difference = one - one
      Assert.assertEquals(difference.real, 0, 0.1)
      Assert.assertEquals(difference.imaginary, 0, 0.1)
    }
 
    @Test
    def testMultiplication() {
      val product = one * two
      Assert.assertEquals(product.real, 2.0, 0.1)
      Assert.assertEquals(product.imaginary, 0, 0.1)
    }
 
    @Test
    def testModulus() {
      Assert.assertEquals(one.modulus, 1.0, 0.1)
      Assert.assertEquals(two.modulus, 2.0, 0.1)
    }
  }

Complex numbers have many applications – one of the them is fractals like the Mandelbrot set. These type of fractals are defined by a recursive formula, where you calculate the next complex number in a series by multiplying the current complex number you have by itself and adding a constant to it. If z is a complex number, you have the relation z * z + c, where c is a constant complex number. This can be graphed in the complex plane with horizontal real values axis and vertical imaginary values axis. I used the so called “escape time algorithm” to draw the fractal. The algorithm scans the points in a small region around the origin on a distance of about 2. Actually I used a square which was probably a little bit too big. Each of these points is used as the c value and is assigned a color based on the number of iterations it takes to escape the region. If it takes more than a predefined number of iterations to escape the pixel gets the default background color.

Mandelbrot

Here is the Maven pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>ComplexNumbers</groupId>
    <artifactId>ComplexNumbers</artifactId>
    <version>1.0</version>
    <repositories>
            <repository>
                <id>scala-tools.org</id>
                <name>Scala-tools Maven2 Repository</name>
                <url>http://scala-tools.org/repo-releases</url>
            </repository>
        </repositories>
        <pluginRepositories>
            <pluginRepository>
                <id>scala-tools.org</id>
                <name>Scala-tools Maven2 Repository</name>
                <url>http://scala-tools.org/repo-releases</url>
            </pluginRepository>
        </pluginRepositories>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.7</version>
            </dependency>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-library</artifactId>
                <version>2.8.0.RC3</version>
            </dependency>
            <dependency>
                 <groupId>org.scala-lang</groupId>
                 <artifactId>scala-swing</artifactId>
                 <version>2.8.0.RC3</version>
            </dependency>
        </dependencies>
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>2.0.2</version>
                    </plugin>
                    <plugin>
                        <groupId>org.scala-tools</groupId>
                        <artifactId>maven-scala-plugin</artifactId>
                        <version>2.9.1</version>
                    </plugin>
                </plugins>
            </pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>compile</phase>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.scala-tools</groupId>
                    <artifactId>maven-scala-plugin</artifactId>
                </plugin>
            </plugins>
    </build>
</project>

We can extend the Mandelbrot idea and use other integer powers instead of 2. The resulting fractals are called the Multibrot set. This calls for an ** operator and also division for negative powers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  def / (that: Complex):Complex = {
    val denominator: Double = Math.pow(that.modulus, 2)
    val realNumerator = real * that.real + imaginary * that.imaginary
    val imagNumerator = imaginary * that.real - real * that.imaginary
 
    return new Complex( realNumerator/ denominator, imagNumerator/ denominator)
  }
 
  def ** (n:Int):Complex = {
    var z = new Complex(r, i)
 
    if(n > 0) {
      for(j <- 1 until n) {
          z *= new Complex(r, i)
      }
    } else {
      for(j <- n until 0) {
         z /= new Complex(r, i)
      }
    }
 
    return z
 
  }

As a side note the Moivre formula did not work properly although it should in theory. Since this is not production code I did not look further for better algorithms. The corresponding unit tests are here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    @Test
    def testDivision() {
      Assert.assertEquals(2, two / one real, 0.1)
      Assert.assertEquals(0, two / one imaginary, 0.1)
    }
 
    @Test
    def testPower() {
      val i = new Complex(0.0, 1.0)
      val i2 = i ** 2
      Assert.assertEquals(i2.real, -1, 0.1)
      Assert.assertEquals(i2.imaginary, 0, 0.1)
 
      Assert.assertEquals(1, one ** 2 real, 0.1)
      Assert.assertEquals(0, one ** 2 imaginary, 0.1)
 
      Assert.assertEquals(4, two ** 2 real, 0.1)
      Assert.assertEquals(0, two ** 2 imaginary, 0.1)
 
      Assert.assertEquals(8, two ** 3 real, 0.1)
      Assert.assertEquals(0, two ** 3 imaginary, 0.1)
    }

I also changed the main application class a bit. Scala has lots of wrappers for Swing, with lots of improvements. Unfortunately, sometimes it gets confusing because the names of the wrapper classes are often the same as the ones from swing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.awt.image.BufferedImage
import java.awt.{Toolkit, Color, Graphics}
import java.util.{Arrays, TimerTask, Timer}
import scala.swing._
import event.ActionEvent
 
object FractalApp extends SimpleSwingApplication {
    val DIM = 400
    val MAX_ITERATION = 300
 
 
    def top = new MainFrame {
      title = "Fractal App"
      preferredSize_=(new Dimension(DIM, DIM))
      contents = new Panel {
        var img = new BufferedImage(DIM,DIM,BufferedImage.TYPE_INT_RGB)
        this.peer.setDoubleBuffered(true)
        val timer = new Timer();
        timer.schedule(new ScheduleTask(), 500);
 
 
        override def paintComponent(g : Graphics2D) : Unit = {
          super.paintComponent(g)
 
          g.drawImage(img, null, 0, 0)
          Toolkit.getDefaultToolkit().sync
 
          g.dispose
 
        }
 
        class ScheduleTask extends TimerTask {
 
          def run():Unit ={
 
            for(d <- -9 to 9) {
              img.flush
              for(i <- 1 until DIM; j <- 1 until DIM) {
                val z0 = new Complex(-2.0 + i * 4.0 / DIM , -2.0 + j * 4.0 / DIM)
                val color = calculateColor(z0, 0, z0, d)
                img.setRGB(i, j, color)
              }
 
              System.out.println(d)
              repaint();
            }
          }
        }
      }
    }
 
    def calculateColor(z:Complex, n:Int, z0:Complex, d:Int):Int ={
      if(n == MAX_ITERATION) {
        return Color.BLACK.getRGB
      }
 
      if(z.modulus >= 2) {
        return n * n * MAX_ITERATION * MAX_ITERATION
      }
 
      calculateColor(z ** d + z0, n + 1, z0, d)
    }
  }

Demo run for powers -10 to 10

Multibrotz

Conclusion

Scala is a new JVM language that is worth looking into. It shows lots of promise and offers new possibilities such as functional programming. You can write short scripts with Scala, Swing applications or anything else that you could write in Java. Scala tries to be better then Java without being Java, however in a statically typed way unlike Ruby or Groovy. Scala is by no means mainstream currently, but it might be by the time Scala Johansson graduates from college, starts a career etcetera, etcetera …

By the author of NumPy Beginner's Guide, NumPy Cookbook and Instant Pygame. If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.
Share
This entry was posted in programming and tagged , . Bookmark the permalink.

One Response to Short guide to Scala

  1. Pingback: Tweets that mention Short guide to Scala | Ivan Idris Blog -- Topsy.com

Comments are closed.