Scala Quick Reference PDF
Scala Quick Reference PDF
nicolas.jorand@crossing-tech.com ! ! ! ! ! 2 / 6! ! ! ! ! ! ! ! v 1.1
Collection TreeSet / TreeMap Lists sample
val ts = TreeSet(9, 3, 1, 8, 0, 2, 7, 4, 6, 5) val truth = "Fly" :: "is" :: "fun" :: Nil
Traversable
scala.collection.immutable.SortedSet[Int] = From Traversable trait:
! Set(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
truth.foreach(print) Flyisfun
Iterable var tm = TreeMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
truth.head Fly
scala.collection.immutable.SortedMap[Int,Char] =
! Map(1 -> x, 3 -> x, 4 -> x) truth.isEmpty false
Map Set Seq List.unzip(zippedTruth) (List(0, 1, 2),
Enumeration List(Fly, is, fun))
object Color extends Enumeration { List.flatten( List(f, l, y, .)
SortedMap SortedSet BitSet Buffer Vector LinearSeq
val Red, Green, Blue = Value List(List('f','l'),List('y'), List('.')))
} truth.count(s => s.length == 3) 2
The main trait is traversable, which is the supertrait of both truth.drop(2) List(fun)
mutable and immutable variations of sequences (Seq), sets, Enumeration with value:
and maps. Sequences are ordered collections, such as object Direction extends Enumeration { truth.exists(s => s == "is") true
arrays and lists. Sets contain at most one of each object, as val Up = Value("goUp") truth.filter(s => s.length == 3) List(Fly, fun)
determined by the == method. Maps contain a collection of val Down = Value("goDown") truth.forall(s => s.endsWith("y")) false
keys mapped to values. } truth.tail List(is, fun)
First try with immutable and switch to mutable only if Direction.Up.id
needed. truth.init List(Fly, is)
res0: Int = 0
truth.last fun
JAVA <-> Scala Conversion Direction(1)
truth.length 3
res1: Direction.Value = goDown
import scala.collection.JavaConversions._ truth.map(s => s + "!") List(Fly!, is!, fun!)
Sets and Maps Lists truth.mkString(",") Fly,is,fun
Class List provides fast access to the head of the list, but truth.remove(s => s.length == 3) List(is)
Immutable Set (default if no explicit import):
not the end. Thus, when you need to build a list by truth.reverse List(fun, is, Fly)
var jetSet = Set("Boeing", "Airbus") appending to the end, you should consider building the list
jetSet += "Lear" backwards by prepending elements to the front, then when truth.sort((s,t) List(fun, Fly, is)
println(jetSet.contains("Cessna")) you’re done, calling reverse to get the elements in the order => s.charAt(0).toLowerCase
you need. < t.charAt(0).toLowerCase)
Mutable Set:
Another alternative, which avoids the reverse operation, is truth.indices List(0, 1, 2)
import scala.collection.mutable.Set
to use a ListBuffer (see next section) truth.toArray Array(Fly, is, fun)
val movieSet = Set("Hitch", "Poltergeist")
movieSet += "Shrek" Creation: truth flatMap (_.toList) List(F, l, y, i, s, f, u, n)
println(movieSet) val oneTwo = List(1, 2) truth partition (_.length == 2) ((List(is),List(Fly, fun))
val threeFour = List(3, 4) truth find (_.charAt(0) == 'a') None
Immutable Map (default if no explicit import): val oneTwoThree = "one" :: "two" :: "three" :: Nil
import scala.collection.immutable.HashMap truth takeWhile List(Fly)
var hashMap = HashMap(1 -> "one", 2 -> "two") Concatenation (“:::”): (_.charAt(0).toLowerCase != 'i')
println(hashMap.get(1)) val oneTwoThreeFour = oneTwo ::: threeFour truth dropWhile List(is, fun)
(_.charAt(0).toLowerCase != 'i')
Mutable Map:
import scala.collection.mutable.Map Prepends (“::” pronounced “cons”): truth forall (_.length > 2) false
val treasureMap = Map[Int, String]() val twoThreeFour = 2 :: threeFour truth exists (_.charAt(0) == 'i') true
treasureMap += (1 -> "Go to island.") Operation on List: truth.foldRight("!")(_ + _) Flyisfun!
treasureMap += (2 -> "Find big X on ground.") truth.reduceRight (_ + _) Flyisfun
Basics:
treasureMap += (3 -> "Dig.") val nums = Set(1, 2, 3) truth.foldRight(List[String]()) List(<Fly>, <is>, <fun>)
println(treasureMap(2)) {(x, list) => ("<"+x+">") :: list}
nums + 5 Set(1, 2, 3, 5)
Conversion immutable to mutable truth.foldLeft("Yes,")(_ + _) Yes,Flyisfun
nums - 3 Set(1, 2)
import scala.collection.mutable List(1,2,3) reduceLeft(_ + _) 6
nums ++ List(5, 6) Set(1, 2, 3, 5, 6)
var mutaSet = mutable.Set.empty ++ immutableSet List.range(9, 1, -3) List[Int] = List(9, 6, 3)
nums -- List(1, 2) Set(3)
Conversion mutable to immutable List.make(5, 'a') List(a, a, a, a, a)
nums & Set(1, 3, 5, 7) Set(1, 3)
val immu = Map.empty ++ muta List.concat( List(b, c)
nums.size 3
List(), List('b'), List('c'))
Map sample nums.contains(2) TRUE
From Iterable traits:
Immutable truth.dropRight(2) List(Fly)
val nums = Map("i" -> 1, "ii" -> 2) import scala.collection.mutable truth.takeRight(2) List(is, fun)
nums + ("vi" -> 6) Map(i -> 1, ii -> 2, vi -> 6) val words = mutable.Set.empty[String] truth.zipWithIndex List( (Fly,0), (is,1),
nums - "ii" Map(i -> 1) (fun,2) )
nums ++ Map(i -> 1, ii -> 2, iii -> 3, v -> 5) words += "thx" Set(thx) truth.indices zip truth List( (0,Fly), (1,is),
List("iii" -> 3, "v" -> 5) words -= "thx" Set() (2,fun) )
nums -- List("i", "ii") Map() words ++= List("α", "β", "γ") Set(!, ", #) truth.grouped(2) Iterator: List(Fly, is),
words --= List("α", "β") Set(!) List(fun)
nums.size 2
truth.sliding(2) Iterator: List(Fly, is),
nums.contains("ii") true words.clear Set() List(is, fun)
nums("ii") 2 truth.sameElements( true
ListBuffer List("Fly", "is", "fun") )
nums.keys Iterator over the strings "i" and "ii"
nums.keySet Set(i, ii) List used to append values in an optimized way (see
general remark of Lists) and to avoid stack overflow.
nums.values Iterator over the integers 1 and 2
val buf = new ListBuffer[Int]
nums.isEmpty false buf += 1
Mutable buf += 2
val wd = scala.collection.mutable.Map.empty[String, Int] 3 +: buf
buf.toList
wd += ("one" -> 1) Map(one -> 1)
List[Int] = List(3, 1, 2)
wd -= "one" Map()
wd ++= Map(one -> 1, two -> 2, three -> 3)
List("one" -> 1,
"two" -> 2,
"three" -> 3)
wd --= Map(three -> 3)
List("one", "two")
wd.getOrElseUpdate return the value for the key ‘k’. If
(k, v) doesn’t exists update wd with the
mapping k->v and return v.
wd.transform( Map(one -> 2)
(s,i) => i + 1)
nicolas.jorand@crossing-tech.com!! ! ! ! ! 3 / 6! ! ! ! ! ! ! v. 1.1
Queues Control Structures
Mutable and immutable first-in-first-out sequence. The only control structure are:
if, while, for, try, match
Immutable
import scala.collection.immutable.Queue IF
val empty = new Queue[Int] println(if (!args.isEmpty) args(0) else "default.txt")
val has1 = empty.enqueue(1) while (imperative Style)
val has123 = has1.enqueue(List(2, 3)) var i = 0
val (element, has23) = has123.dequeue while (i < args.length) {
element: Int = 1 has23: scala.collection.immutable.Queue println(args(i))
[Int] = Queue(2,3) i += 1
Mutable }
import scala.collection.mutable.Queue
FOR
val queue = new Queue[String] for (arg <- args) println(arg)
queue += "a"
for (i <- 0 to 5) print(i) 012345
queue ++= List("b", "c") for (i <- 0 until 5) print(i) 01234
queue
scala.collection.mutable.Queue[String] = Queue(a, b, c) FILTERING
queue.dequeue for ( file <- filesHere
res0: String = a if file.isFile;
queue if file.getName.endsWith(".scala")
res1: scala.collection.mutable.Queue[String] = Queue(b, c) ) println(file)
nicolas.jorand@crossing-tech.com ! ! ! ! ! 4 / 6! ! ! ! ! ! ! v 1.1
Functions Improve the code XML
Scala has first-class functions. Not only can you define Using closure to reduce code duplication. val myXML =
functions and call them, but you can write down functions as object FileMatcher { <html>
unnamed literals and then pass them around as values. <head>
private def filesHere = (new java.io.File(".")).listFiles
General Definition: <script type="text/javascript">
private def filesMatching(matcher: String => Boolean) =
def name(x: Type, y: Type)[: Type] = { ... } for (file <- filesHere; if matcher(file.getName)) document.write("Hello")</script>
yield file <script type="text/javascript">
Function literal (closed term):
(x: Type, y: Type) => x + y def filesEnding(query: String) = document.write("world!")</script>
filesMatching(_.endsWith(query)) </head>
Function literal (closure or open term): <body id="bID">some Text</body>
var more = 10 def filesContaining(query: String) =
filesMatching(_.contains(query)) </html>
(x: Type, y: Type) => x + y + more
def filesRegex(query: String) = myXML \ "body"
Save function in a variable: filesMatching(_.matches(query)) res0: scala.xml.NodeSeq =
var increase = (x: Int) => { println(“Add 1”); x + 1} } <body id="bID">some Text</body>
increase: (Int) => Int = <function> (myXML \ "body").text
increase(10) Simplifying code res1: String = some Text
Add1 Avoid loops to search an elements. myXML \\ "script"
res0: Int = 11 def hasNeg(nums: List[Int]) = nums.exists(_ < 0) res2: scala.xml.NodeSeq =
<script type="text/javascript">
Placeholder: def hasOdd(nums: List[Int]) = nums.exists(_ % 2 == 1)
numbers.filter(x => x > 0) document.write("Hello")</script>
<script type="javascript">
numbers.filter(_ > 0) Currying document.write("world!")</script>
Partially applied function: Currying is the technique of transforming a function that (myXML \\ "script")(0) \ "@type"
someNumbers.foreach(x => println(x)) takes more than one parameter into a function that takes res3: scala.xml.NodeSeq = text/javascript
someNumbers.foreach(println _) multiple parameter lists, the primary use for currying is to
specialize functions for particular types of data. Build an XML
someNumbers.foreach(println ) // all same result
def multiplier(i: Int)(factor: Int) = i * factor val simple = <a> {3 + 4} </a>
knowing the function: val byFive = multiplier(5) _ res3: scala.xml.Elem = <a> 7 </a>
def sum(a: Int, b: Int, c: Int) = a + b + c val byTen = multiplier(10) _ val xml = scala.xml.XML.loadString("<test>evt</test>")
sum(1, 2, 3) xml: scala.xml.Elem = <test>event</test>
res0: Int = 6 It’s possible to curry a function:
val f = (x: Double, y: Double, z: Double) => x * y / z CDATA
val a = sum _
val fc = f.curry val body = <body> {PCData(in.getBodyasTxt)} </body>
a(1, 2, 3)
res1: Int = 6 Control structures Serialization
val b = sum(1, _: Int, 3) abstract class Plane{
b(5) // same as sum(1, 5, 3) This is used to implement patterns like “loan pattern”: val description: String
def withPrintWriter(file: File) (op: PrintWriter => Unit) { val year: Int
res15: Int = 9
val writer = new PrintWriter(file) val licence: String
Repeated parameters try { override def toString = description
def echo(args: String*) = for (arg <- args) println(arg) op(writer) def toXML =
Cast an array as repeated parameters } finally { <plane>
val arr = Array("What's", "up", "doc?") writer.close() <desc>{description}</desc>
echo(arr: _*) } <year>{year}</year>
} <licence>{licence}</licence>
to call this code </plane>
val file = new File("date.txt") }
void (java) = Unit (Scala)
withPrintWriter(file) { defined class Plane
writer => writer.println(new java.util.Date) val piper = new Plane {
No Return statement: } val description = "Versatile Plane"
def max2(x: Int, y: Int) = if (x > y) x else y
val year = 1967
val licence = "HB-PNJ"
A Function could have a symbol as name. This By Name parameters }
allow to add for eg the operator “+” just by defining
def + (that: Type) A by-name parameter is specified by omitting the piper: Plane = Versatile Plane
parentheses that normally accompany a function parameter. piper.toXML
Once defined like that the parameter is not evaluated until res0: scala.xml.Elem =
Parameterized Methods it’s called within the function.
<plane>
def myWhile(conditional: => Boolean)(f: => Unit) {
Scala’s parameterized types are similar to Java and C# <year>1967</year>
generics and C++ templates. if (conditional) {
f <licence>HB-PNJ</licence>
onInOut[+Ti, +To]( infoInput:Ti ): To
myWhile(conditional)(f) </plane>
Named parameter / Default } Deserialization
Possibility to get the parameter by name instead of their } def fromXML(node: scala.xml.Node): Plane =
position. Furthermore, you can assign a default value new Plane {
To use this code
def draw(x: Int y: Int, dblBuff: Boolean = false) = { ... } val year = (node \ "year").text.toInt
var count = 0
draw(dblBuff=true, x=0, y=10) val licence = (node \ "licence").text
myWhile(count < 5) {
}
Implicit println("still awesome")
fromXML: (scala.xml.Node)Plane
count += 1
This is a standard function definition starting with implicit. } Save to file
Once declared like that the compiler can use it to perform scala.xml.XML.saveFull("pa28.xml",
type conversion. node, "UTF-8", true, null)
implicit def intToString(x: Int) = x.toString
Load from file
Rules: val loadnode = xml.XML.loadFile("pa28.xml")
Scope An inserted implicit conversion must be in XML and Pattern
scope as a single identifier, or be
associated with the source or target type A pattern embedded in {} can use the full Scala pattern lan-
of the conversion. guage, including binding new variables, performing type
Non-Ambiguity An implicit conversion is only inserted if tests, and ignoring content using the _ and _* patterns
there is no other possible conversion to def proc(node: scala.xml.Node): String =
insert. node match {
One-at-a-time Only one implicit is tried. case <a>{contents}</a> => "It's an a: "+ contents
Explicits-First Whenever code type checks as it is case <b>{contents}</b> => "It's a b: "+ contents
written, no implicits are attempted.
case _ => "It's something else."
}
If the tag has children then use the “_*” notation:
case <a>{contents @ _*}</a> => "It's an a: "+ contents
notice the “@” is a pattern with a variable binding.
nicolas.jorand@crossing-tech.com!! ! ! ! ! 5 / 6! ! ! ! ! ! ! v. 1.1
If you want to match against a sequence without specifying
Case Classes how long it can be, you can specify _* as the last element of Partial Function
the pattern.
To create a case class add the keyword case on the class A partial function of type PartialFunction[A, B] is a unary
Definition: expr match { function where the domain does not necessarily include all
case class Var(name: String) // get case List(0, _*) => println("found it") values of type A. The function isDefinedAt allows to test
case class Config(var name: String = “Me”) // get/set case _ => dynamically if a value is in the domain of the function.
} PartialFunction trait defines a method orElse that takes
Effects: another PartialFunction.
1/ No needs to add new to create a class instance: Tuple Pattern val truthier: PartialFunction[Boolean, String] = {
val v = Var("x") def tupleDemo(expr: Any) = expr match { case true => "truthful" }
case (a, b, c) => println("matched "+ a + b + c) val fallback: PartialFunction[Boolean, String]= {
2/ All arguments in the parameter list are maintained as case x => "sketchy" }
fields: case _ =>
v.name } val tester = truthier orElse fallback
println(tester(1 == 1)) println(tester(2 + 2 == 5))
3/ Compiler adds “natural” implementations of methods Applied on List;
toString, hashCode, and equals: val List(a, b, c) = fruit Patterns in for expressions
println(v) a: String = apples
Var(x) b: String = oranges Using Tuple pattern:
for ((country, city) <- capitals)
c: String = pears
You can have secondary constructors in case println("The capital of "+ country +" is "+ city)
classes, but they wont overload the apply method Typed Pattern Using Option type:
generated that has the same argument list. def generalSize(x: Any) = x match { val results = List(Some("apple"), None, Some("orange"))
You’ll have to use new to create instances with case s: String => s.length for (Some(fruit) <- results) println(fruit)
those constructors. case m: Map[_, _] => m.size apple
case _ => -1 orange
Copy Method }
On a case class a copy method is generated which allow to
Extractor
create a modified copy of an existing instance. Variable-Binding pattern An extractor in Scala is an object that has a method called
item match { unapply as one of its members.
The definition is case (id, p @ Person(_, _, Manager)) =>
case class A[T](a: T, b: Int) { object EMail {
format("%s is overpaid.\n", p) // The injection method (optional)
// def copy[T'](a: T' = this.a, b: Int = this.b): A[T'] =
case (id, p @ Person(_, _, _)) => def apply(user: String, domain: String) =
// new A[T'](a, b)
format("%s is underpaid.\n", p) # user +"@"+ domain
}
case _ => // The extraction method (mandatory)
val a1: A[Int] = A(1, 2)
} def unapply(str: String): Option[(String, String)] = {
val a2: A[String] = a1.copy(a = "someString")
# val parts = str split "@"
Pattern Matching Sealed Classes # if (parts.length == 2) Some(parts(0), parts(1))
If you know that the case class hierarchy is unlikely to # else None
General definition: change and you can define the whole hierarchy in one file. }
selector match { alternatives } In this situation, you can add the sealed keyword to the }
Match example declaration of the common base class. When sealed, the
def matchOn(shape: Shape) = compiler knows all the possible classes that could appear in The unapply method is called an extraction and can be used
the match expression, because all of them must be defined in pattern matching;
shape match { in the same source file. val x: Any = ...
case Circle(center, radius) => So, if you cover all those classes in the case expressions x match { case EMail(user, domain) => ... }
println("Circle: center = "+center+", radius = (either explicitly or through shared parent classes), then you
"+radius) can safely eliminate the default case expression. Regular Expressions
case Rectangle(ll, h, w) => sealed abstract class HttpMethod()
case class Connect(body: String) extends HttpMethod the syntax is inherited from JAVA.
println("Rectangle: lower-left = "+ll+", height = import scala.util.matching.Regex
"+h+", width = "+w) case class Delete (body: String) extends HttpMethod
case class Get # (body: String) extends HttpMethod val Decimal = new Regex("""(-)?(\d+)(\.\d*)?""")
case Triangle(p1, p2, p3) =>
case class Head# (body: String) extends HttpMethod // Or more simpler
println("Triangle: point1 = "+p1+", point2 =
"+p2+", point3 = "+p3) case class Options (body: String) extends HttpMethod """(-)?(\d+)(\.\d*)?""".r
case _ => println("Unknown shape!"+shape) case class Post# (body: String) extends HttpMethod Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
case class Put# (body: String) extends HttpMethod
} Searching:
case class Trace# (body: String) extends HttpMethod
val input = "-1.0 to 99 by 3"
Wildcard Pattern No default case is necessary ( otherwise -> error ) for (s <- Decimal findAllIn input) println(s)
Wildcards can also be used to ignore parts of an object that -1.0
Option Type
you do not care about. 99
expr match { As everything is an object in Scala, instead of returning null 3
case BinOp(_, _, _) => from a method then use the object None.If the return is not Decimal findFirstIn input
println(expr +"is a binary operation") null then return Some(x) where is the actual value.
res1: Option[String] = Some(-1.0)
case _ => println("It's something else") def show(x: Option[String]) = x match {
Decimal findPrefixOf input
} case Some(s) => s
res2: Option[String] = Some(-1.0)
case None => "?"
Constant Pattern } Extracting:
def describe(x: Any) = x match { val Decimal(sign, integerpart, decimalpart) = "-1.23"
case 1 # # => "one" Patterns in variable definitions sign: String = -
case true# # => "truth" val myTuple = (123, "abc") integerpart: String = 1
val (number, string) = myTuple decimalpart: String = .23
case "hello" | “Ciao”# => "hi!"
number: Int = 123 string: java.lang.String = abc val Decimal(sign, integerpart, decimalpart) = "1.0"
case i: Int # # => "scala.Int"
sign: String = null
case Nil # # => "the empty list"
case _ # # => "something else"
Case sequences as partial functions integerpart: String = 1
decimalpart: String = .0
} react {
case (name: String, actor: Actor) =>
Variable Pattern actor ! getip(name) act()
expr match { case msg =>
case 0 => "zero" println("Unhandled message: "+ msg) act()
case <tag>{ t }</tag> => t }
case somethingElse => "not zero: "+ somethingElse val second: PartialFunction[List[Int],Int] = {
} case x :: y :: _ => y
A variable pattern matches any object, just like a wildcard. }
Unlike a wildcard, Scala binds the variable to whatever the
object is.
Sequence Pattern
expr match {
case List(0, _, _) => println("found it")
case _ =>
}
nicolas.jorand@crossing-tech.com!! ! ! ! ! 6 / 6! ! ! ! ! ! ! v. 1.1