You can also go back to the FAQ page.
The following imports class Map from package scala.collection.mutable:
import scala.collection.mutable.Map
We can import several classes from the same package in a single statement:
import scala.collection.mutable.{Map, Set, Buffer}
We can import all classes in a package, using the _ wildcard:
import scala.collection.mutable._
We can also rename imports:
import scala.collection.mutable.{Map => MutableMap}
and with a similar notation, exclude specific classes:
import scala.collection.mutable.{_, Map => _, Set => _}
The latter imports everything from package scala.collection.mutable, except Map and Set.
Scala’s imports are relative and thus we can import everything from scala.collection and scala.collection.mutable with:
import scala.collection._ import mutable._
Since package scala is imported implicitly anyway, we can also write the above as:
import collection._ import mutable._
To make package names absolute, we can prefix them with _root_:
import _root_.scala.collection.mutable.Map
We may import Java packages:
import java.beans.XMLEncoder import javax.swing.JTable
(or .NETs when compiled to that VM)
An example scala file:
import collection.mutable.{Map => MutableMap} //alias an import import _root_.scala.collection.immutable.Map //non-relative import import scala.concurrent.{Lock, Channel} //imports both scala.concurrent.Lock and scala.concurrent.Channel import scala.Array._ //imports all members of object Array object ImportExample extends Application { val mmap = MutableMap("one" -> 1, "two" -> 2, "three" -> 3) assume(mmap.isInstanceOf[scala.collection.mutable.Map[String, int]]) val imap = Map("one" -> 1, "two" -> 2, "three" -> 3) assume(imap.isInstanceOf[scala.collection.immutable.Map[String, int]]) val source = Array(1, 2, 3) val target = Array(1, 5, 3) copy(source, 1, target, 1, 1)//copy method was imported //import an instance's members class Cat { val catName = "fluffy" def meow { println("meow") } } val cat = new Cat //import the instance's members import cat._ meow assume(catName == "fluffy") }
There are two ways to write simple integer loops:
for (i <- 0 until 1000000) { ... }
var i = 0; while (i < 1000000) { ...; i = i+1 }
The second can be more efficient, but the first is usually considered as cleaner code. To make the loop include 1000000, use to instead of until.
Using higher-order functions defined in scala.Iterable and elsewhere (scala.List in particular) can often replace for the best a more traditional loop.
For-comprehensions are translated into a series of calls to the functions map, flatMap and filter of the originating object (see ScalaRef 6.16).
for(n <- List( 5, 7, 2, 4) if n % 2 == 1) yield n * n
is equivalent to
List(5, 7, 2, 4).filter(n => n % 2 == 1).map(n => n * n)
Lazyness and Eagerness in for comprehensions
The results may seem surprising in the following for comprehension:
var done = false for { i <- List(1,2) if !done } { println(i+" "+done) assert( !done ) done = true }
There is a second iteration and an assert, even though done is set to true after the first iteration. This is due to the expanded List.filter( x ⇒ !done ) being strictly (eagerly) evaluated, where done is “false” during the call to filter (i.e. no actual iteration has taken place yet).
Using List(1,2).projection or “1 to 2” forces lazy evaluation, i.e. for each iteration the next element is evaluated. and works as expected. see list-manipulation for more details on lazy vs eager for lists.
It should be noted that using code with such side effects can also reduce composibility of a given comprehension (whether used inside a for or by calling filter etc by hand).
Also important is that lazy vs strict evaluation can exhibit different performance characteristics (in terms of both memory usage and processing time) for different code. If in doubt profile.
An exception (actually an instance of Throwable) can be caught in a catch clause. The specific exception type is detected using pattern matching:
try { ... } catch { case ioe: IOException => ... // more specific cases first ! case e: Exception => ... }
Java’s catch clauses are really nothing more than a limited form of pattern matching.
toString method is automatically redefined to print the name of the case class and all its arguments.equals method is automatically redefined to compare two instances of the same case class structurally rather than by identity.hashCode method is automatically redefined to give equal values for instances that are the same when compared with equals.Since Scala 2.7.0 a case class can extend a case class.
Case classes are commonly used to create user-defined value types – data structures, if you will. Some obvious examples might be complex numbers or street addresses. Objects of a value type are identified by their data values, not by their memory addresses. Value types typically have no mutable state because value objects whose data values are immutable can safely be duplicated and shared at will. Unrestricted duplicating and sharing is crucial for data that has to be stored on disk or transmitted to a different program or different computer. Value types certainly can be defined as ordinary classes, but using case classes simplifies the process.
You must have a stone-age version of scala... since quite a while, there is a _root_ package which is used internally to find the parts of the scala library all programs depend on. Hence, it is possible to use scala in package names now, if the urge should arise.
You can group expressions without the need to create new classes
object Test extends Application { def tupleTest = (1, 2, 3) val (a, b ,c) = tupleTest println("a:" + a + ", b:" + b + ", c:" + c) val t = tupleTest println("a:" + t._1 + ", b:" + t._2 + ", c:" + t._3) }
Above, tupleTest is of type Tuple3[Int, Int, Int] which can be written as [Int, Int, Int]. This shorthand syntax was introduced in Scala 2.4. Before, there was no special syntax for tuples. They had to be created as any other case class, e.g., through Tuple3(1, 2, 3) or through the unnumbered generator Tuple(1, 2, 3). Both forms are still available.
Tuple1 to Tuple22 are defined. Pair can be used as Tuple2. Triple can be used as Tuple3.
There are two ways to write lists, one using the infix operator ::, and the other using the List constructor. Their meaning is the same, and you can use both ways in pattern matching
val t = List( 1, 2, 3, 4, 5) val u = 1 :: 2 :: 3 :: 4 :: 5 :: Nil t match { case 1::2::rest => true case List(1,2,rest@_*) => true // equivalent }
immutable
val immutable = Map(1 -> "one", 2 -> "two", 3 -> "three") //assignment returns a new map val map2 = immutable(2) = "2" assume(immutable == Map(1 -> "one", 2 -> "two", 3 -> "three")) assume(map2 == Map(1 -> "one", 2 -> "2", 3 -> "three"))
mutable
val map = new scala.collection.mutable.HashMap[String, Any] map("likes") = "cheese" assume( map("likes") == "cheese") assume( map.get("likes") == Some("cheese") ) assume( map.get("fakeKey") == None) map += "name" -> "Gromit" assume( map("name") == "Gromit") map += "id" -> 1234 assume( map.get("id") == Some(1234) ) assume( map("id") == 1234) map.get("id") match { case Some(idval) => assume(1234 == idval) case None => fail("no value found") }
//custom classes as keys to a map case class AnotherCustomKey(someval:int, someString:String) { //hashCode and equals are implemented for you } val map = new HashMap[AnotherCustomKey, int] map += AnotherCustomKey(1,"333") -> 1 assume(map.get(AnotherCustomKey(1, "333")) == Some(1)) assume(map.get(AnotherCustomKey(2, "222")) == None) //if a case class can not be used, you must override equals and hashCode class CustomKey(val someval:int) { override def hashCode: int = someval override def equals(any:Any): Boolean = { any.isInstanceOf[CustomKey] && any.asInstanceOf[CustomKey].someval == someval } } val map2 = new HashMap[CustomKey, int] map2 += new CustomKey(1) -> 1 assume(map2.get(new CustomKey(1)) == Some(1)) assume(map2.get(new CustomKey(2)) == None)
There are some predefined functions for this, no need to import them.
For preconditions you can use the functions assume( cond:Boolean) and assume( cond:Boolean, msg:String)
def sqrt( v: Double) = { assume( v >= 0, "sqrt parameter must be non-negative") Math.sqrt( v) ; }
You have also assert( cond:Boolean) and assert( cond:Boolean, msg:String)
There is a compiler switch -noassert to skip asserts and assumptions on final executables.
For unrecoverable errors there is the function error( msg: String) that throws an Error
For recoverable exceptions you can derive java.lang.RuntimeException
In Scala, array access are made using the syntax of normal method calls.
val x = Array(3,2,1); assert(x(0) == 3) assert(x(1) == 2) assert(x(2) == 1) x(0) = 4
Array is just treated like a normal object: it has any apply method (which is called in an expression like x(0)), and an update method (which is the spelled out version of the statement x(0) = 4).
There is nothing that prevents you from making use of this trick. Below is a program that demonstrates how an object can be turned into something like a dictionary. For real dictionaries, using the collection.Map types is preferrable of course.
object dictionary { val data = Array(null, "A","B","C") def apply(x:String) = x match { case "one" => data(1) case "two" => data(2) case "three" => data(3) } def update(x:String,y:String) = x match { case "one" => data(1) = y // ...this gets turned to data.update(1,y) case "two" => data(2) = y case "three" => data(3) = y } def main(args:Array[String]) { // ...shorthand for this.apply("one") Console.println(this("one")+","+this("two")+","+this("three")) this("one") = "X" // ...and this becomes this.update("one","X") this("two") = "Y" this("three") = "Z" Console.println(this("one")+","+this("two")+","+this("three")) } }
A method with a “normal” (call-by-value) argument is declared like this
def foo(x:Bar) = { val a = x val b = x }
Whenever foo is called with an expression such as the “abc” in foo(abc), the expression abc will be evaluated once and the result will be passed to foo. The variables x, a, and b will all be references to the same result value.
A method with a lazy (call-by-name) argument is declared like this
def foo(x:=>Bar) = { val a = x val b = x }
In this case, when foo(abc) is executed, abc won’t be evaluated before foo is called. Instead, x will be equivalent to the expression “abc” rather than the value that abc returns. So in the code above abc will be evaluated twice. The first result will go into the variable a, the second will go into the variable b.
A method that takes a no-argument function (a thunk) is declared like this
def foo(x:() => Bar) = { val a = x val b = x val c = x() }
To call foo(abc), abc must be a function or evaluate to a function. As with call-by-name, the function will not be evaluated before calling foo. In that sense it looks like a call-by-name lazy argument and in fact call-by-name is implemented as a thunk “under the hood.” The difference is that with explicit thunks the assignments to a and b only create aliases to the abc function, they don’t evaluate the function. To evaluate the function an expression like the assignment to c must be used.
Lazy values allow you to turn call-by-name lazy arguments into call-by-need lazy arguments.
def foo(x: => Bar) = { lazy val a = x //... }
If foo(abc) is executed then using x anywhere in the method will normally cause a (re)evaluation of the abc expression. However, the assignment of x to the lazy value a does not cause abc to be evaluated. Instead, the first use of a will cause abc to be evaluated but each subsequent use of a will reuse the same result.
Here are some relatively brief tutorials and references you can use:
Rather more extensive is “Scala by Example”, a PDF (150+ pages) by Martin Odersky that is included with the Scala documentation package.
More extensive still is the book Programming in Scala by Martin Oderksy, Lex Spoon, and Bill Venners. It is over 500 pages long. The book is not completely finished yet (as of April 2008) but you can purchase a PDF of the current draft from http://www.artima.com/shop/forsale .
See also the Scala/Java interoperability FAQs