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 | ... |