Scala Quick Reference
Scala Quick Reference
Separator between
identifiers and type
annotations.
Assignment.
Operators
Import
import java.awt._ // All classes under java.awt
import java.io.File
import java.io.File._ // Import all File static methods
import java.util.{Map, HashMap} // only the 2 classes
Arithmetics
Relational
Logical
Bitwise
(and, or, xor, inv)
Bitwise shift
(left, right, unsigned right)
+, -, *, /, %
>, < ,<=, >=, ==, !=
&&, ||, !
&, |, ^, ~
<<, >>, >>>
Narrow import:
def doIt() = {
import java.math.BigDecimal.{ONE}
println(ONE)
}
val one = 1
Rename import:
import java.math.BigDecimal.{
ONE => _, # #
// Exclude ONE
=> Used in function literals numbers.filter(x => x < 0)
ZERO => JAVAZERO # // Rename it
Rich
Operation
separate the argument
to
}
list from the function
Scala provides rich wrapper around basic types via implicit println(JAVAZERO)
body.
conversions.
<- Used in for
for (arg <- args)
import statements are relative, not absolute. To
in
Code
Result
create an absolute path, start with _root_
comprehensions
generator expressions.
0 max 5
5
import _root_.scala.collectionsjcl._
<: Upper bounds (a subtype def apply[T <: U](x: T)
0 min 5
0
of)Used in parameterized
Packages
-2.7 abs
2.7
and abstract type
declarations to constrain
-2.7 round
-3L
File
names
dont
have to match the type names,
the allowed types.
the package structure does not have to match the
1.5 isInfinity
false
<% View bounds( apply
def m [A <% B](args): R
directory structure. So, you can define packages in
(1.0 / 0) isInfinity
true
implicit convertion).Used = ...
files independent of their physical location.
in parameterized and
4 to 6
Range(4,5,6)
Traditional:
abstract type declarations
"nick" capitalize
Nick
to convert the type using
package com.xtech.scala
view.
"nicolas" drop 2
colas
Nested:
>: Lower bounds (supertype def append[U >: T](x: U)
package com{
Literals
of)Used in parameterized =
package scala { class A }
and abstract type
Integer
declarations to constrain
package util { class B } }
the allowed types.
val dec = 31
Decimal Integer
Tuples
# Refer to a type
val ic: MyClass#myType
val hex = 0XFF
Hexa Integer
declaration nested in
= ...
Are
immutable
and
can
contain
different types of elements.
val
long
=
31L
Long
(l
or
L)
another type
val nena = (99, "Luftballons",1983)
val little: Short = 367 Short
@ Marks an annotation.
@deprecated def bad() =
println(nena._1)
val littler: Byte = 38
Byte
Symbol
val s = 'aSymbol
println(nena._2) .... println(nena(0)) (not same Type in list)
def doIt(r: Symbol)
Floating point
doIt(s); print(s.name)
_ Usage Summary
val double = 1.2345 Double
Curried functions
val
e
=
1.234e4
Double
(e
or
E)
If a method takes 0 or one parameter you can drop
def twice(op: Double => Double) (x: Double) = op(op(x))
the dot and parentheses when calling the function.
val float = 1.234F
Float (f or F)
twice(_ + 1) (5)
Character and String
res8: Double = 7.0
Variables
val aChar = D
Char
twice(x => x + 1)(5) // More verbose
val unicode = \u0043
Unicode Char
Immutable (Final)
Existential types
val msg = "Hello, world!"
val string = string
String
Labeling something that is unknown:
val msg: String = "Hello, world!"
class Marshaller[T] { def marshall(t:T) = {println(t)} }
val s = its you Raw String ( Its you )
val big = new java.math.BigInteger("12345")
new Marshaller[String]
Special character
Mutable
var greets = "Hello, world!"
var greets: String = "Hello, world!"
Lazy initialization
(only on Immutable)
object Demo {
lazy val x = { println("initializing x"); "done" }
}
Basic Types
Value Type Range
Byte
8-bit signed twos complement integer
(-27 to 27 - 1, inclusive)
Short
16-bit signed twos complement integer
(-215 to 215 - 1, inclusive)
Int
32-bit signed twos complement integer
(-231 to 231 - 1, inclusive)
Long
64-bit signed twos complement integer
(-263 to 263 - 1, inclusive)
Char
16-bit unsigned Unicode character
(0 to 216 - 1, inclusive)
String
a sequence of Chars
Float
32-bit IEEE 754 single-precision float
Double 64-bit IEEE 754 double-precision float
Boolean true or false
Literal
Meaning
\n
\b
backspace (\u0008)
\t
tab (\u0009)
\f
\r
\\
backslash (\u005C)
Function literals
someNumbers.filter(_ > 0)
Boolean
Boolean (true | false)
Check
Import statements
abc.isInstanceOf[String]
re0: Boolean = true
import com.xtech.cf._
Cast
Match expressions
3.asInstanceOf[Double]
res0: Double = 3.0
Initialization
Runtime Representation
classOf[String]
res7: java.lang.Class[String] = class java.lang.String
!
1 / 6!
Setter
Class Hierachy
Variance
Any
Equivalent to
java.long.Object
AnyVal
AnyRef
Unit
Double
Boolean
Float
Traits
A traits is like a java interface at the difference that its
possible to implements methods and fields on it. Traits can
be reused into classes by mixing the trait to the class or by
extending it.
ScalaObject
All java.*
ref. types
Actors
All scala.*
ref. types
Definition
trait Saxo {
def play() {
println("Nice sound!")
}
}
Null
Definition
With
class Instrument
class Baryton extends Instrument {
override def toString = "Baryton"
}
val baryton = new Baryton() with Saxo
Simple class:
class ChecksumAccumulator {
private var sum = 0
def add(b: Byte): Unit = sum += b
def checksum(): Int = ~(sum & 0xFF) + 1
}
Ordered Traits
Constructor
The default constructor (primary constructor) is defined by
the body class and parameters are listed after the class
name. Other constructors (auxiliary constructor) are defined
by the function definition this():
class Rational(n: Int, d: Int) {
require(d != 0)
val numer: Int = n
val denom: Int = d
def this(n: Int) = this(n, 1) // auxiliary constructor
}
To hide the constructor make it private:
class Rational private(n: Int, d: Int)
Getter / Setter
The Ordered trait defines <, >, <=, and >= just by
implementing one method, compare.
class Rational(n: Int, d: Int) extends Ordered[Rational]{
// ...
def compare(that: Rational) =
(this.numer * that.denom) - (that.numer * this.denom)
}
Mixing
Once a trait is mixed into a class, you can alternatively call it
a mixin.Traits are a way to inherit from multiple class-like
constructs, but they differ in important ways from the
multiple inheritance present in many languages. With traits,
the method called is determined by a linearization of the
classes and traits that are mixed into a class.
Linearization algorithm
Abstract
To Start it:
SimpleActor.start()
To start a thread immediately use the utility method actor:
import scala.actors._
val seriousActor2 = actor {
for (i <- 1 to 5)
println("Do it!.")
}
Extends
class Alto extends Saxo {
override def toString = "Alto"
}
Nothing
import scala.actors._
object SimpleActor extends Actor {
def act() {
for (i <- 1 to 5) {
println("Do it!")
Thread.sleep(1000)
}
}
}
To send a message:
echoActor ! Hello
received message: hi there
To use the current thread use self:
self ! "hello"
self.receive { case x => x }
res6: Any = hello
self.receiveWithin(1000) { case x => x }
res7: Any = TIMEOUT
Change Scheduler:
Run it on the main Thread
trait SingleThread extends Actor{
override protected def scheduler() =
#
#
new SingleThreadScheduler
}
Run all actors in the Main thread:
Scheduler.impl = new SingleThreadScheduler
Thread reuse
Writing an actor to use react instead of receive is
challenging, but pays off in performance. Because react
does not return, the calling actors call stack can be
discarded, freeing up the threads resources for a different
actor. At the extreme, if all of the actors of a program use
react, then they can be implemented on a single thread.
As empiric rule:
- Actors that are message-heavy are better implemented
with while(true)/receive (Hogging a thread).
class C1 {def m = List("C1")}
- Actors with non trivial work are better implemented with
trait T1 extends C1 {override def m ={ "T1" :: super.m}}
loop/react.
trait T2 extends C1 {override def m ={ "T2" :: super.m}} object NameResolver extends Actor {
trait
T3
extends
C1
{override
def
m
={
"T3"
::
super.m}}
Inheritance
import java.net.{InetAddress, UnknownHostException}
class C2 extends T2 {override def m ={ "C2" :: super.m}} def act() {
class A extends B
class C extends C2 with T1 with T2 with T3{
react {
Call super constructor
override def m ={ "C" :: super.m}
case (name: String, actor: Actor) =>
class A(param: String) extends B(param: String)
}
#
#
actor ! getIp(name)
#
#
act()
# Linearization
Description
1C
+ type of the instance.
case "EXIT" => println("Exiting.") // quit
Singleton / Static
2 C, T3, C1,
+ farthest on the right (T3)
case msg => println("Unhandled message: "+ msg)
3 C, T3, C1, T2, C1
+ T2
#
#
act()
Singleton objects are objects with only on instance
4 C, T3, C1, T2, C1, T1, C1 + T1
in the whole JVM.
}
5 C, T3, C1, T2, C1, T1, C1, + C2
}
There is no static in Scala, instead use the companion
C2, T2, C1
object to support class-level operation and properties. A
def getIp(name: String): Option[InetAddress] = {
6 C, T3, T2, T1, C2, T2, C1 - duplicates C1 but last
companion is a singleton
try {
7 C, T3, T1, C2, T2, C1
- duplicates T2 but last
class Book private (title: String)
Some(InetAddress.getByName(name))
8 C, T3, T1, C2, T2, C1,
done.
object Book {
ScalaObject, AnyRef, Any
}catch {
val favorites= """"Java Puzzlers", "Design Patterns""""
case _:UnknownHostException => None
SelfType
}
def apply(title: String) = {
Redefines the type of this. Must be a subclass of all the self }
type of all its base class.
println("Book construction ...");new Book(title)
}
class Animal {this: Dog with Friend => ... }
}
def main(args: Array[String]){ ... }
}
printf("My favorites are : %s\n", Book.favorites)
My favorites are : "Java Puzzlers", "Design Patterns"
Book("Digital Fortress")
Book construction ...
res1: Book = Book@2012a961
2 / 6!
v 1.1
Collection
TreeSet / TreeMap
Traversable
Iterable
Map
Lists sample
val ts = TreeSet(9, 3, 1, 8, 0, 2, 7, 4, 6, 5)
scala.collection.immutable.SortedSet[Int] =
!
Set(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
var tm = TreeMap(3 -> 'x', 1 -> 'x', 4 -> 'x')
scala.collection.immutable.SortedMap[Int,Char] =
!
Map(1 -> x, 3 -> x, 4 -> x)
Set
Seq
Enumeration
Flyisfun
Fly
false
(List(0, 1, 2),
List(Fly, is, fun))
List.flatten(
List(List('f','l'),List('y'), List('.')))
truth.count(s => s.length == 3)
The main trait is traversable, which is the supertrait of both
truth.drop(2)
Enumeration
with
value:
mutable and immutable variations of sequences (Seq), sets,
object Direction extends Enumeration {
truth.exists(s => s == "is")
and maps. Sequences are ordered collections, such as
arrays and lists. Sets contain at most one of each object, as val Up = Value("goUp")
truth.filter(s => s.length == 3)
determined by the == method. Maps contain a collection of
val Down = Value("goDown")
truth.forall(s => s.endsWith("y"))
keys mapped to values.
}
truth.tail
First try with immutable and switch to mutable only if
Direction.Up.id
truth.init
needed.
res0: Int = 0
truth.last
Direction(1)
JAVA <-> Scala Conversion
truth.length
res1: Direction.Value = goDown
import scala.collection.JavaConversions._
truth.map(s => s + "!")
Lists
truth.mkString(",")
Sets and Maps
truth.remove(s => s.length == 3)
Class List provides fast access to the head of the list, but
Immutable Set (default if no explicit import):
not the end. Thus, when you need to build a list by
truth.reverse
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)
youre done, calling reverse to get the elements in the order => s.charAt(0).toLowerCase
println(jetSet.contains("Cessna"))
you need.
< t.charAt(0).toLowerCase)
Mutable Set:
truth.indices
Another
alternative,
which
avoids
the
reverse
operation,
is
import scala.collection.mutable.Set
to use a ListBuffer (see next section)
truth.toArray
val movieSet = Set("Hitch", "Poltergeist")
truth flatMap (_.toList)
Creation:
movieSet += "Shrek"
val oneTwo = List(1, 2)
truth partition (_.length == 2)
println(movieSet)
val threeFour = List(3, 4)
truth find (_.charAt(0) == 'a')
Immutable Map (default if no explicit import):
val oneTwoThree = "one" :: "two" :: "three" :: Nil
truth takeWhile
import scala.collection.immutable.HashMap
(_.charAt(0).toLowerCase != 'i')
Concatenation (:::):
var hashMap = HashMap(1 -> "one", 2 -> "two")
val oneTwoThreeFour = oneTwo ::: threeFour
truth dropWhile
println(hashMap.get(1))
(_.charAt(0).toLowerCase != 'i')
Mutable Map:
truth forall (_.length > 2)
Prepends (:: pronounced cons):
import scala.collection.mutable.Map
val twoThreeFour = 2 :: threeFour
truth exists (_.charAt(0) == 'i')
val treasureMap = Map[Int, String]()
truth.foldRight("!")(_ + _)
treasureMap += (1 -> "Go to island.")
Operation on List:
treasureMap += (2 -> "Find big X on ground.")
truth.reduceRight (_ + _)
Basics:
treasureMap += (3 -> "Dig.")
truth.foldRight(List[String]())
val nums = Set(1, 2, 3)
println(treasureMap(2))
{(x, list) => ("<"+x+">") :: list}
nums + 5
Set(1, 2, 3, 5)
truth.foldLeft("Yes,")(_ + _)
Conversion immutable to mutable
nums - 3
Set(1, 2)
import scala.collection.mutable
List(1,2,3) reduceLeft(_ + _)
nums ++ List(5, 6)
Set(1, 2, 3, 5, 6)
var mutaSet = mutable.Set.empty ++ immutableSet
List.range(9, 1, -3)
nums -- List(1, 2)
Set(3)
List.make(5, 'a')
Conversion mutable to immutable
nums & Set(1, 3, 5, 7)
Set(1, 3)
val immu = Map.empty ++ muta
List.concat(
nums.size
3
List(), List('b'), List('c'))
Map sample
nums.contains(2)
TRUE
From Iterable traits:
Immutable
truth.dropRight(2)
val nums = Map("i" -> 1, "ii" -> 2)
import scala.collection.mutable
truth.takeRight(2)
nums + ("vi" -> 6)
Map(i -> 1, ii -> 2, vi -> 6)
val words = mutable.Set.empty[String]
truth.zipWithIndex
nums - "ii"
Map(i -> 1)
words
+=
"thx"
Set(thx)
truth.indices zip truth
nums ++
Map(i -> 1, ii -> 2, iii -> 3, v -> 5)
words -= "thx"
Set()
List("iii" -> 3, "v" -> 5)
words ++= List("", "", "")
Set(, , )
truth.grouped(2)
nums -- List("i", "ii")
Map()
words --= List("", "")
Set()
nums.size
2
truth.sliding(2)
words.clear
Set()
nums.contains("ii")
true
SortedMap
SortedSet
nums("ii")
nums.keys
nums.keySet
nums.values
nums.isEmpty
BitSet
Buffer
Vector
LinearSeq
2
Iterator over the strings "i" and "ii"
Set(i, ii)
Iterator over the integers 1 and 2
false
truth.sameElements(
List("Fly", "is", "fun") )
ListBuffer
List(f, l, y, .)
2
List(fun)
true
List(Fly, fun)
false
List(is, fun)
List(Fly, is)
fun
3
List(Fly!, is!, fun!)
Fly,is,fun
List(is)
List(fun, is, Fly)
List(fun, Fly, is)
List(0, 1, 2)
Array(Fly, is, fun)
List(F, l, y, i, s, f, u, n)
((List(is),List(Fly, fun))
None
List(Fly)
List(is, fun)
false
true
Flyisfun!
Flyisfun
List(<Fly>, <is>, <fun>)
Yes,Flyisfun
6
List[Int] = List(9, 6, 3)
List(a, a, a, a, a)
List(b, c)
List(Fly)
List(is, fun)
List( (Fly,0), (is,1),
(fun,2) )
List( (0,Fly), (1,is),
(2,fun) )
Iterator: List(Fly, is),
List(fun)
Iterator: List(Fly, is),
List(is, fun)
true
3 / 6!
v. 1.1
Queues
Control Structures
Immutable
import scala.collection.immutable.Queue
val empty = new Queue[Int]
val has1 = empty.enqueue(1)
val has123 = has1.enqueue(List(2, 3))
val (element, has23) = has123.dequeue
element: Int = 1 has23: scala.collection.immutable.Queue
[Int] = Queue(2,3)
IF
println(if (!args.isEmpty) args(0) else "default.txt")
Mutable
import scala.collection.mutable.Queue
val queue = new Queue[String]
queue += "a"
queue ++= List("b", "c")
queue
scala.collection.mutable.Queue[String] = Queue(a, b, c)
queue.dequeue
res0: String = a
queue
res1: scala.collection.mutable.Queue[String] = Queue(b, c)
Stacks
var i = 0
while (i < args.length) {
println(args(i))
i += 1
}
FOR
for (arg <- args) println(arg)
for (i <- 0 to 5) print(i)
for (i <- 0 until 5) print(i)
012345
01234
FILTERING
for ( file <- filesHere
if file.isFile;
if file.getName.endsWith(".scala")
) println(file)
If you add more than one filter on a generator, the
filters if clauses must be separated by semicolons.
This is why theres a semicolon after the
if file.isFile
NESTED
def fileLines(file: java.io.File) =
scala.io.Source.fromFile(file).getLines.toList
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala"); // <-- semi-colon
line <- fileLines(file)
trimmed = line.trim // Mid-stream variable bindings
if trimmed.matches(pattern)
) println(file +": "+ trimmed)
grep(".*gcd.*")
Arrays
Creation:
val greetStrings: Array[String] = new Array[String](3)
val greetStrings = new Array[String](3)
val greetStrings = Array("Hello",,, world!\n)
Access:
greets(0) = "Hello" or greets.update(0, "Hello")
greets(1) = ", "
greets(2) = "world!\n"
for (i <- 0 to 2) print(greets(i))
TRY
explode array
def max(values: Int*) = values.foreach(print)
max(Array(1,2,3,4,5): _*) // :_* tell compiler to pass
12345
each elements
try {
val f = new FileReader("input.txt") // Use and close file
} catch {
case ex: FileNotFoundException => // missing file
case ex: IOException => // Handle other I/O error
}
ArrayBuffer
An ArrayBuffer is like an array, except that you can
additionally add and remove elements from the beginning
and end of the sequence.
import scala.collection.mutable.ArrayBuffer
val buf = new ArrayBuffer[Int]()
buf += 1
buf += 2
FINALLY
Used only to close opened resources.
val file = new FileReader("input.txt")
try {
// Use the file
} finally {
file.close() // Be sure to close the file
}
MATCH
firstArg match {
case "salt" #
case "chips" #
case "eggs" #
case _ #
}
=> println("pepper")
=> println("salsa")
=> println("bacon")
=> println("huh?")
FOREACH
(functional Style to print Main Args):
args.foreach((arg: String) => println(arg))
args.foreach(arg => println(arg))
args.foreach(println)
4 / 6!
v 1.1
Functions
XML
val myXML =
Scala has first-class functions. Not only can you define
Using closure to reduce code duplication.
<html>
functions and call them, but you can write down functions as object FileMatcher {
unnamed literals and then pass them around as values.
<head>
private def filesHere = (new java.io.File(".")).listFiles
<script type="text/javascript">
General Definition:
private def filesMatching(matcher: String => Boolean) =
document.write("Hello")</script>
def name(x: Type, y: Type)[: Type] = { ... }
for (file <- filesHere; if matcher(file.getName))
<script type="text/javascript">
yield file
Function literal (closed term):
document.write("world!")</script>
(x: Type, y: Type) => x + y
def filesEnding(query: String) =
</head>
filesMatching(_.endsWith(query))
Function literal (closure or open term):
<body id="bID">some Text</body>
def filesContaining(query: String) =
var more = 10
</html>
filesMatching(_.contains(query))
(x: Type, y: Type) => x + y + more
myXML \ "body"
def filesRegex(query: String) =
Save function in a variable:
res0: scala.xml.NodeSeq =
filesMatching(_.matches(query))
var increase = (x: Int) => { println(Add 1); x + 1}
<body id="bID">some Text</body>
}
increase: (Int) => Int = <function>
(myXML \ "body").text
Simplifying code
increase(10)
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)
document.write("Hello")</script>
numbers.filter(x => x > 0)
<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
multiple parameter lists, the primary use for currying is to
someNumbers.foreach(println _)
specialize functions for particular types of data.
Build an XML
someNumbers.foreach(println ) // all same result
val simple = <a> {3 + 4} </a>
def multiplier(i: Int)(factor: Int) = i * factor
knowing the function:
res3: scala.xml.Elem = <a> 7 </a>
val byFive = multiplier(5) _
def sum(a: Int, b: Int, c: Int) = a + b + c
val xml = scala.xml.XML.loadString("<test>evt</test>")
val byTen = multiplier(10) _
sum(1, 2, 3)
xml: scala.xml.Elem = <test>event</test>
Its possible to curry a function:
res0: Int = 6
val f = (x: Double, y: Double, z: Double) => x * y / z
CDATA
val a = sum _
val body = <body> {PCData(in.getBodyasTxt)} </body>
val fc = f.curry
a(1, 2, 3)
Serialization
res1: Int = 6
Control structures
abstract class Plane{
val b = sum(1, _: Int, 3)
This is used to implement patterns like loan pattern:
val description: String
b(5) // same as sum(1, 5, 3)
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 =
} finally {
Cast an array as repeated parameters
<plane>
val arr = Array("What's", "up", "doc?")
writer.close()
<desc>{description}</desc>
echo(arr: _*)
}
<year>{year}</year>
}
<licence>{licence}</licence>
</plane>
to call this code
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"
By Name parameters
A Function could have a symbol as name. This
}
allow to add for eg the operator + just by defining
piper: Plane = Versatile Plane
A by-name parameter is specified by omitting the
def + (that: Type)
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
its called within the function.
<plane>
def myWhile(conditional: => Boolean)(f: => Unit) {
Scalas parameterized types are similar to Java and C#
<year>1967</year>
if
(conditional)
{
generics and C++ templates.
<licence>HB-PNJ</licence>
f
onInOut[+Ti, +To]( infoInput:Ti ): To
</plane>
myWhile(conditional)(f)
Deserialization
def fromXML(node: scala.xml.Node): Plane =
new Plane {
val year = (node \ "year").text.toInt
val licence = (node \ "licence").text
}
fromXML: (scala.xml.Node)Plane
Implicit
This is a standard function definition starting with implicit.
Once declared like that the compiler can use it to perform
type conversion.
implicit def intToString(x: Int) = x.toString
Save to file
scala.xml.XML.saveFull("pa28.xml",
node, "UTF-8", true, null)
Load from file
val loadnode = xml.XML.loadFile("pa28.xml")
Rules:
Scope
5 / 6!
v. 1.1
Case Classes
To create a case class add the keyword case on the class
Definition:
case class Var(name: String)
// get
case class Config(var name: String = Me) // get/set
Effects:
Tuple Pattern
Applied on List;
val List(a, b, c) = fruit
a: String = apples
b: String = oranges
c: String = pears
Typed Pattern
Copy Method
On a case class a copy method is generated which allow to
create a modified copy of an existing instance.
The definition is
case class A[T](a: T, b: Int) {
// def copy[T'](a: T' = this.a, b: Int = this.b): A[T'] =
//
new A[T'](a, b)
}
val a1: A[Int] = A(1, 2)
val a2: A[String] = a1.copy(a = "someString")
Extractor
Variable-Binding pattern
item match {
case (id, p @ Person(_, _, Manager)) =>
format("%s is overpaid.\n", p)
case (id, p @ Person(_, _, _)) =>
format("%s is underpaid.\n", p)
case _ =>
}
Sealed Classes
Pattern Matching
General definition:
selector match { alternatives }
Match example
def matchOn(shape: Shape) =
shape match {
case Circle(center, radius) =>
println("Circle: center = "+center+", radius =
"+radius)
case Rectangle(ll, h, w) =>
println("Rectangle: lower-left = "+ll+", height =
"+h+", width = "+w)
case Triangle(p1, p2, p3) =>
println("Triangle: point1 = "+p1+", point2 =
"+p2+", point3 = "+p3)
case _ => println("Unknown shape!"+shape)
}
Partial Function
A partial function of type PartialFunction[A, B] is a unary
function where the domain does not necessarily include all
values of type A. The function isDefinedAt allows to test
dynamically if a value is in the domain of the function.
PartialFunction trait defines a method orElse that takes
another PartialFunction.
val truthier: PartialFunction[Boolean, String] = {
case true => "truthful" }
val fallback: PartialFunction[Boolean, String]= {
case x => "sketchy" }
val tester = truthier orElse fallback
println(tester(1 == 1)) println(tester(2 + 2 == 5))
Regular Expressions
the syntax is inherited from JAVA.
import scala.util.matching.Regex
val Decimal = new Regex("""(-)?(\d+)(\.\d*)?""")
// Or more simpler
"""(-)?(\d+)(\.\d*)?""".r
Decimal: scala.util.matching.Regex = (-)?(\d+)(\.\d*)?
Searching:
val input = "-1.0 to 99 by 3"
No default case is necessary ( otherwise -> error )
for (s <- Decimal findAllIn input) println(s)
-1.0
Wildcards can also be used to ignore parts of an object that
Option
Type
you do not care about.
99
expr match {
As everything is an object in Scala, instead of returning null 3
from a method then use the object None.If the return is not Decimal findFirstIn input
case BinOp(_, _, _) =>
null then return Some(x) where is the actual value.
println(expr +"is a binary operation")
res1: Option[String] = Some(-1.0)
def show(x: Option[String]) = x match {
case _ => println("It's something else")
Decimal findPrefixOf input
case
Some(s)
=>
s
}
res2: Option[String] = Some(-1.0)
case None => "?"
Constant Pattern
}
Extracting:
val Decimal(sign, integerpart, decimalpart) = "-1.23"
def describe(x: Any) = x match {
Patterns in variable definitions
sign: String = case 1 #
#
=> "one"
integerpart: String = 1
val myTuple = (123, "abc")
case true#
#
=> "truth"
decimalpart: String = .23
val (number, string) = myTuple
case "hello" | Ciao# => "hi!"
val Decimal(sign, integerpart, decimalpart) = "1.0"
number: Int = 123 string: java.lang.String = abc
case i: Int #
#
=> "scala.Int"
sign: String = null
case Nil #
#
=> "the empty list"
Case sequences as partial functions integerpart: String = 1
case _ #
#
=> "something else"
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
Wildcard Pattern
Sequence Pattern
expr match {
case List(0, _, _) => println("found it")
case _ =>
}
[email protected]!!
6 / 6!
v. 1.1