

In Scala everything is an object, even numbers and functions.
Scala 2.9.1 was released on 2011-08-29.
Useful Links
Like most modern programming languages, you can execute programs stored in files or you can use the REPL (Read-Eval-Print Loop).
To use the REPL invoke scala with no arguments:
You can put your script in a file, and invoke scala with the filename:
println("Hello, world")
If you need commandline arguments, use the args array:
// Print a greeting for the one whose name is given as the first commandline argument.
print("Hello");
if (args.isEmpty || args(0).trim.isEmpty) {
println
} else {
println(", " + args(0))
}
Your script can also be comprised of an object with a method called main taking in an
array of strings for the arguments:
object CodepointComputer {
def codepointsFor(s: String) = {
s.toList.map(c => c.toInt)
}
def main(args: Array[String]) {
if (args.isEmpty || args(0).trim.isEmpty) {
println("Missing argument")
} else {
println(codepointsFor(args(0)))
}
}
}
It works as before:
In addition, this style allows you to compile and interpret separately:
scalac command above.
Let's continue getting acquainted with the look and feel of Scala scripts:
import java.util.{Date, Locale}
import java.text.DateFormat._
val now = new Date
val frenchDateForatter = getDateInstance(LONG, Locale.FRANCE)
println(frenchDateForatter format now)
println(getDateInstance(LONG, Locale.US) format now)
println(getDateInstance(SHORT, Locale.CHINA) format now)
// A script to write the Fibonacci numbers up to and including the first commandline argument.
object FibonacciLister {
def main(args: Array[String]) {
val n = args(0).toInt
var (a, b) = (0, 1)
while (b <= n) {
print(b + " ")
var olda = a
a = b
b = a + b
}
println
}
}
object TimerExample {
/**
* Runs the passed in function pausing approximately one second in between calls,
* as long as the function returns true.
*/
def oncePerSecond(callback: () => Boolean) {
while (callback()) {
Thread sleep 1000
}
}
/**
* Counts down from 10 to 1, approximately once per second.
*/
def main(args: Array[String]) {
var count = 10;
oncePerSecond(() => {println(count); count -= 1; count > 0})
}
}
Good terms to know:
| Type | Description |
|---|---|
| Unit | Has only the single value ()
|
| Boolean | Has only the two values true and false
|
| Byte | The 8-bit signed integers: -128...127 |
| Short | The 16-bit signed integers: -32768...32767 |
| Int | The 32-bit signed integers: -2147483648...2147483647 |
| Long | The 64-bit signed integers: -9223372036854775808..9223372036854775807 |
| Float | The 32-bit IEEE 754 floating point numbers |
| Double | The 64-bit IEEE 754 floating point numbers |
| Char | The Unicode characters with codepoints <= 0xFFFF |
| String | The finite sequence of Char objects
|
| Null | Has only the single value null
|
| Nothing | Subtype of every type |
| Any | Supertype of every type |
| AnyRef | Supertype of every reference type |
import java.util.Arrays
def addSeven(x: Int) = x + 7
def multiplier(n: Int) = (x: Int) => x * n
def timesFour = multiplier(4)
def twice(f: (Int) => Int, x: Int) = f(f(x))
var timesThree = (x: Int) => x * 3
val collatz = (n: Int) => if (n % 2 == 0) n / 2 else 3 * n + 1
println(addSeven(5));
println(timesFour(10));
println(timesThree(10));
var n = 27
var a: Array[Int] = Array(n)
while (n != 1) {
n = collatz(n)
a ++= Array(n)
}
println(Arrays.toString(a))
Here are a couple starter classes:
/**
* A simple immutable circle with a center point and a radius.
*/
class Circle(x: Double, y: Double, radius: Double) {
def center = (x, y)
def area = math.Pi * radius * radius
def perimeter = 2.0 * math.Pi * radius
def move(dx: Double, dy: Double) = new Circle(x + dx, y + dy, radius)
def expand(factor: Double) = new Circle(x, y, radius * factor)
override def toString = "Circle at (" + x + "," + y + ") with radius " + radius
}
/**
* A simple mutable circle with a center point and a radius.
*/
class MutableCircle(private var x: Double, private var y: Double, private var radius: Double) {
def center = (x, y)
def area = math.Pi * radius * radius
def perimeter = 2.0 * math.Pi * radius
def move(dx: Double, dy: Double) = {
x += dx
y += dy
this
}
def expand(factor: Double) = {
radius *= factor
this
}
override def toString = "MutableCircle at (" + x + "," + y + ") with radius " + radius
}
Compile them, then let's see them in action:
Here's an abstract class for animals and three concrete subclasses.
abstract class Animal(name: String) {
def speak = name + " says " + sound
def sound: String
}
class Cow(name: String) extends Animal(name) {
override def sound() = "moooooo"
}
class Horse(name: String) extends Animal(name) {
override def sound() = "neigh"
}
class Sheep(name: String) extends Animal(name) {
override def sound() = "baaaa"
}
var h = new Horse("CJ")
println(h.speak)
var c = new Cow("Bessie")
println(c.speak)
println(new Sheep("Little Lamb").speak)
A for comprehension is just syntactic sugar for certain (chains of) method calls. Examples are better than explanations here.
scala> val a = List(3, 6, 5, 7, 8, 1, 2, 3, 2, 14, 8)
a: List[Int] = List(3, 6, 5, 7, 8, 1, 2, 3, 2, 14, 8)
scala> a.map(x => x * 3)
res0: List[Int] = List(9, 18, 15, 21, 24, 3, 6, 9, 6, 42, 24)
scala> a.map(_ * 3)
res1: List[Int] = List(9, 18, 15, 21, 24, 3, 6, 9, 6, 42, 24)
scala> for (x <- a) yield x * 3
res2: List[Int] = List(9, 18, 15, 21, 24, 3, 6, 9, 6, 42, 24)
scala> a.filter(_ < 5).map(_ * 3)
res3: List[Int] = List(9, 3, 6, 9, 6)
scala> for (x <- a; if x < 5) yield x * 3
res4: List[Int] = List(9, 3, 6, 9, 6)
scala> a.filter(_ < 5).foreach(x => print(x * 3))
93696
scala> for (x <- a; if x < 5) {print(x * 3)}
93696
scala> for (x <- 0 until 4; y <- 0 until 4) yield (x, y)
res7: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,0), (0,1), (0,2), (0,3),
(1,0), (1,1), (1,2), (1,3), (2,0), (2,1), (2,2), (2,3), (3,0), (3,1), (3,2), (3,3))
scala> (0 until 4).flatMap(x => (0 until 4).map(y => (x, y)))
res8: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,0), (0,1), (0,2), (0,3),
(1,0), (1,1), (1,2), (1,3), (2,0), (2,1), (2,2), (2,3), (3,0), (3,1), (3,2), (3,3))
Many unit testing frameworks exist for Scala. One of the most popular is ScalaTest. Start with the Quick Start. You'll want to start with FunSuite.
class Point(val x: Double, val y: Double) {
def distanceToOrigin() = math.sqrt(x * x + y * y);
override def toString = "(" + x + "," + y + ")"
}
import org.scalatest.FunSuite
class PointSuite extends FunSuite {
test("construction") {
val p = new Point(3, -4)
assert(p.x === 3)
assert(p.y === -4)
}
test("making strings") {
val p = new Point(3, -4)
assert(p.toString() === "(3.0,-4.0)")
}
test("distance to origin") {
val p = new Point(3, -4)
assert(p.distanceToOrigin() === 5)
}
}
To run:
$ scalac -cp scalatest-1.6.1.jar point.scala pointtest.scala $ scala -cp scalatest-1.6.1.jar org.scalatest.tools.Runner -p . -o -s PointSuite
In Scala 2.9.1, there are 57 packages in the Scala Standard Library.
| Package | Description |
|---|---|
| scala | Core Scala types. They are always available without an explicit import. |
| scala.actors | A library that provides both asynchronous and synchronous messaging to allow for concurrent programming without explicit synchronization. |
| scala.actors.remote | |
| scala.actors.scheduler | ... |
| scala.annotation | ... |
| scala.annotation.target | ... |
| scala.annotation.unchecked | ... |
| scala.collection | Contains the base traits and objects needed to use and extend Scala's collection library. |
| scala.collection.generic | ... |
| scala.collection.immutable | ... |
| scala.collection.interfaces | ... |
| scala.collection.mutable | ... |
| scala.collection.parallel | ... |
| scala.collection.parallel.immutable | ... |
| scala.collection.parallel.mutable | ... |
| scala.collection.script | ... |
| scala.compat | ... |
| scala.concurrent | ... |
| scala.io | ... |
| scala.math | ... |
| scala.parallel | ... |
| scala.ref | ... |
| scala.reflect | ... |
| scala.reflect.generic | ... |
| scala.runtime | ... |
| scala.swing | ... |
| scala.swing.event | ... |
| scala.swing.model | ... |
| scala.sys | ... |
| scala.sys.process | ... |
| scala.testing | ... |
| scala.text | ... |
| scala.util | ... |
| scala.util.automata | ... |
| scala.util.continuations | ... |
| scala.util.control | ... |
| scala.util.grammar | ... |
| scala.util.logging | ... |
| scala.util.matching | ... |
| scala.util.parsing.ast | ... |
| scala.util.parsing.combinator | ... |
| scala.util.parsing.combinator.lexical | ... |
| scala.util.parsing.combinator.syntactical | ... |
| scala.util.parsing.combinator.testing | ... |
| scala.util.parsing.combinator.token | ... |
| scala.util.parsing.input | ... |
| scala.util.parsing.json | ... |
| scala.util.regexp | ... |
| scala.xml | ... |
| scala.xml.dtd | ... |
| scala.xml.factory | ... |
| scala.xml.include | ... |
| scala.xml.include.sax | ... |
| scala.xml.parsing | ... |
| scala.xml.persistent | ... |
| scala.xml.pull | ... |
| scala.xml.transform | ... |