Symbolics Operators Import import java.awt._ // All classes under java.awt -> Returns a two-element Map( 1 -> "A", 2 -> "B") +, -, *, /, % Arithmetics import java.io.File tuple containing the key (1).->(“A”) >, < ,<=, >=, ==, != Relational import java.io.File._ // Import all Fileʼ static methods and value &&, ||, ! Logical import java.util.{Map, HashMap} // only the 2 classes _ A placeholder, used in import com.xtech._ imports, function literals, &, |, ^, ~ Bitwise Narrow import: case _ => value.toString (and, or, xor, inv) etc. numbers.filter(_ < 0) def doIt() = { <<, >>, >>> Bitwise shift import java.math.BigDecimal.{ONE} : Separator between def add(i: Int): Int = ... (left, right, unsigned right) identifiers and type println(ONE) annotations. } The operator “==” check the value equality on = Assignment. val one = “1” reference AND primitive type. Rename import: import java.math.BigDecimal.{ ONE => _, // Exclude ONE => Used in function literals numbers.filter(x => x < 0) Rich Operation ZERO => JAVAZERO // Rename it to separate the argument } ! 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 " comprehensions in Code Result create an absolute path, start with _root_ generator expressions. 0 max 5 5 <: Upper bounds (a subtype def apply[T <: U](x: T) import _root_.scala.collectionsjcl._ of)Used in parameterized 0 min 5 0 and abstract type -2.7 abs 2.7 Packages declarations to constrain -2.7 round -3L the allowed types. File names don’t have to match the type names, 1.5 isInfinity false the package structure does not have to match the <% View bounds( apply def m [A <% B](args): R directory structure. So, you can define packages in implicit convertion).Used = ... (1.0 / 0) isInfinity true files independent of their “physical” location. in parameterized and 4 to 6 Range(4,5,6) abstract type declarations Traditional: to convert the type using "nick" capitalize “Nick” package com.xtech.scala view. "nicolas" drop 2 “colas” Nested: >: Lower bounds (supertype def append[U >: T](x: U) package com{ of)Used in parameterized = Literals and abstract type package scala { class A } declarations to constrain Integer package util { class B } } the allowed types. val dec = 31 Decimal Integer # Refer to a type val ic: MyClass#myType val hex = 0XFF Hexa Integer Tuples declaration nested in = ... another type val long = 31L Long (“l” or “L”) Are immutable and can contain different types of elements. @ Marks an annotation. @deprecated def bad() = val little: Short = 367 Short val nena = (99, "Luftballons",”1983”) ʻ Symbol val s = 'aSymbol val littler: Byte = 38 Byte println(nena._1) def doIt(: Symbol) println(nena._2) .... println(nena(0)) (not same Type in list) doIt(s); print(s.name) Floating point val double = 1.2345 Double _ Usage Summary Curried functions If a method takes 0 or one parameter you can drop val e = 1.234e4 Double (“e” or “E”) the dot and parentheses when calling the function. val float = 1.234F Float (“f” or “F”) def twice(op: Double => Double) (x: Double) = op(op(x)) twice(_ + 1) (5) Character and String res8: Double = 7.0 Variables val aChar = ʻDʼ Char twice(x => x + 1)(5) // More verbose Immutable (Final) val unicode = ʼ\u0043ʼ Unicode Char Existential types val msg = "Hello, world!" val string = “string” String Labeling something that is unknown: val msg: String = "Hello, world!" val s = “”” itʼs “you” “”” Raw String ( It’s “you” ) class Marshaller[T] { def marshall(t:T) = {println(t)} } val big = new java.math.BigInteger("12345") new Marshaller[String] Mutable Special character res1: Marshaller[String] = Marshaller@7896b1b8 var greets = "Hello, world!" Literal Meaning res1.isInstanceOf[Marshaller[_]] var greets: String = "Hello, world!" res4: Boolean = true \n line feed (\u000A) Lazy initialization same as: (only on Immutable) \b backspace (\u0008) .isInstanceOf[T forSome {type T <: Marshaller[String]}] object Demo { \t tab (\u0009) Function literals lazy val x = { println("initializing x"); "done" } \f form feed (\u000C) } someNumbers.filter(_ > 0) \r carriage return (\u000D) Partially applied functions Basic Types \” double quote (\u0022) def sum(a: Int, b: Int, : Int) = a + b + c Value Type Range \’ single quote (\u0027) val a = sum _ Byte 8-bit signed two’s complement integer \\ backslash (\u005C) a: (Int, Int, Int) => Int = (-27 to 27 - 1, inclusive) val b = sum(1, _: Int, 3) Boolean Short 16-bit signed two’s complement integer b: (Int) => Int = (-215 to 215 - 1, inclusive) val bool = true Boolean (true | false) b(2) Int 32-bit signed two’s complement integer Check res10: Int = 6 (-231 to 231 - 1, inclusive) “abc”.isInstanceOf[String] Import statements Long 64-bit signed two’s complement integer (-263 to 263 - 1, inclusive) re0: Boolean = true import com.xtech.cf._ Char 16-bit unsigned Unicode character Cast Match expressions (0 to 216 - 1, inclusive) 3.asInstanceOf[Double] case _ => “default value” // Default case value String a sequence of Chars res0: Double = 3.0 Initialization Float 32-bit IEEE 754 single-precision float Runtime Representation Double 64-bit IEEE 754 double-precision float var age: Int = _ // age initialized to 0 Boolean true or false classOf[String] Setter res7: java.lang.Class[String] = class java.lang.String Redefined a setter method: def age_ = (a: Int) { if(girl) age = a - 5 else age = a } [email protected]!!!!!!1 / 6!! ! ! ! ! ! v. 1.1 Class Hierachy Variance Actors Covariance: Ability to accept sub-classes. import scala.actors._ Any “T <: Pet” or “+T” : (as T extends Pet) object SimpleActor extends Actor { Equivalent to def act() { java.long.Object Contra-variance: Ability to accept base classes “T >: Cat” or “-T” : (as T is superType of Cat) for (i <- 1 to 5) { AnyVal AnyRef println("Do it!") Traits Thread.sleep(1000) } A traits is like a java interface at the difference that it’s Unit Double ScalaObject 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. All java.* All scala.* Boolean Float To Start it: ref. types ref. types Definition SimpleActor.start() trait Saxo { def play() { To start a thread immediately use the utility method actor: import scala.actors._ println("Nice sound!") val seriousActor2 = actor { } for (i <- 1 to 5) Helper for type } Null inference println("Do it!.") Extends } Nothing class Alto extends Saxo { override def toString = "Alto" Send message to Actor; import scala.actors._ } Definition val echoActor = actor { With while (true) { Simple class: class Instrument receive { class ChecksumAccumulator { class Baryton extends Instrument { case msg => println("received message: "+ msg) private var sum = 0 override def toString = "Baryton" } def add(b: Byte): Unit = sum += b } } def checksum(): Int = ~(sum & 0xFF) + 1 val baryton = new Baryton() with Saxo } } Ordered Traits To send a message: Constructor echoActor ! “Hello” The Ordered trait defines <, >, <=, and >= just by received message: hi there The default constructor (primary constructor) is defined by implementing one method, compare. the body class and parameters are listed after the class class Rational(n: Int, d: Int) extends Ordered[Rational]{ To use the current thread use self: name. Other constructors (auxiliary constructor) are defined // ... self ! "hello" by the function definition “this()”: def compare(that: Rational) = self.receive { case x => x } class Rational(n: Int, d: Int) { (this.numer * that.denom) - (that.numer * this.denom) res6: Any = hello require(d != 0) } self.receiveWithin(1000) { case x => x } res7: Any = TIMEOUT val numer: Int = n Mixing val denom: Int = d Change Scheduler: def this(n: Int) = this(n, 1) // auxiliary constructor 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 Run it on the main Thread constructs, but they differ in important ways from the trait SingleThread extends Actor{ To hide the constructor make it private: multiple inheritance present in many languages. With traits, override protected def scheduler() = class Rational private(n: Int, d: Int) the method called is determined by a linearization of the new SingleThreadScheduler classes and traits that are mixed into a class. } Getter / Setter Linearization algorithm Run all actors in the Main thread: Once a val or var is defined within a class the corresponding Scheduler.impl = new SingleThreadScheduler accessor methods are generated. The generated methods 1 Put the actual type of the instance as the first element. use the same privilege as the field. Thread reuse Only the getter is generated in case of val. 2 Starting with the right most parent type and working The methods don’t follow the JavaBean nomenclature. left,compute the linearization of each type, appending Writing an actor to use react instead of receive is its linearization to the cumulative linearization. (Ignore challenging, but pays off in performance. Because react To generate JavaBean getter and setter add the annotation: ScalaObject, AnyRef, and Any for now.) does not return, the calling actor’s call stack can be @scala.reflect.BeanProperty var level: Int = _ discarded, freeing up the thread’s resources for a different actor. At the extreme, if all of the actors of a program use Abstract 3 Working from left to right, remove any type if it react, then they can be implemented on a single thread. abstract class Document { appears again to the right of the current position. As empiric rule: def footNotes: Array[String] // abstract method 4 Append ScalaObject, AnyRef, and Any. - Actors that are message-heavy are better implemented var nbOfPages : Int // abstract Field class C1 {def m = List("C1")} with “while(true)/receive” (Hogging a thread). - Actors with non trivial work are better implemented with type paper // abstract type 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 { Inheritance trait T3 extends C1 {override def m ={ "T3" :: super.m}} import java.net.{InetAddress, UnknownHostException} class A extends B class C2 extends T2 {override def m ={ "C2" :: super.m}} def act() { class C extends C2 with T1 with T2 with T3{ react { Call super constructor override def m ={ "C" :: super.m} class A(param: String) extends B(param: String) case (name: String, actor: Actor) => } actor ! getIp(name) # Linearization Description act() Singleton / Static 1 C + type of the instance. case "EXIT" => println("Exiting.") // quit 2 C, T3, C1, + farthest on the right (T3) case msg => println("Unhandled message: "+ msg) Singleton objects are objects with only on instance 3 C, T3, C1, T2, C1 + T2 act() in the whole JVM. 4 C, T3, C1, T2, C1, T1, C1 + T1 } 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 6 C, T3, T2, T1, C2, T2, C1 - duplicates C1 but last def getIp(name: String): Option[InetAddress] = { companion is a singleton 7 C, T3, T1, C2, T2, C1 - duplicates T2 but last try { class Book private (title: String) 8 C, T3, T1, C2, T2, C1, done. Some(InetAddress.getByName(name)) object Book { ScalaObject, AnyRef, Any }catch { val favorites= """"Java Puzzlers", """"" SelfType case _:UnknownHostException => None } def apply(title: String) = { Redefines the type of this. Must be a subclass of all the self } println("Book construction ...");new Book(title) type of all its base class. } } 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

[email protected] !! ! ! ! 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 truth.init List(Fly, is) needed. res0: Int = 0 truth.last fun JAVA <-> Scala Conversion Direction(1) res1: Direction.Value = goDown truth.length 3 import scala.collection.JavaConversions._ truth.map(s => s + "!") List(Fly!, is!, fun!) Sets and Maps Lists truth.mkString(",") Fly,is,fun truth.remove(s => s.length == 3) List(is) Immutable Set (default if no explicit import): Class List provides fast access to the head of the list, but 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: truth.indices List(0, 1, 2) import scala.collection.mutable.Set Another alternative, which avoids the reverse operation, is to use a ListBuffer (see next section) val movieSet = Set("Hitch", "Poltergeist") truth.toArray Array(Fly, is, fun) 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(, , ) println(treasureMap(2)) {(x, list) => ("<"+x+">") :: list} nums + 5 Set(1, 2, 3, 5) truth.foldLeft("Yes,")(_ + _) Yes,Flyisfun Conversion immutable to mutable 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) List.make(5, 'a') List(a, a, a, a, a) Conversion mutable to immutable 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), List(fun) nums.size 2 words --= List("α", "β") Set(!) truth.sliding(2) Iterator: List(Fly, is), nums.contains("ii") true words.clear Set() List(is, fun) nums("ii") 2 ListBuffer truth.sameElements( true nums.keys Iterator over the strings "i" and "ii" List("Fly", "is", "fun") ) 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)

[email protected]!! ! ! ! ! 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)

Stacks If you add more than one filter on a generator, the filter’s if clauses must be separated by semicolons. Mutable and immutable last-in-first-out sequence. This is why there’s a semicolon after the “if file.isFile” Mutable import scala.collection.mutable.Stack NESTED val stack = new Stack[Int] def fileLines(file: java.io.File) = stack.push(1) scala.io.Source.fromFile(file).getLines.toList stack.push(2) stack.top def grep(pattern: String) = res0: Int = 2 for ( stack file <- filesHere res1: scala.collection.mutable.Stack[Int] = Stack(1, 2) if file.getName.endsWith(".scala"); // <-- semi-colon line <- fileLines(file) stack.pop trimmed = line.trim // Mid-stream variable bindings res2: Int = 2 if trimmed.matches(pattern) stack ) println(file +": "+ trimmed) res3: scala.collection.mutable.Stack[Int] = Stack(1) grep(".*gcd.*") Arrays Return new collection: for clauses yield body Creation: val greetStrings: Array[String] = new Array[String](3) Generates a collection with elements of each iteration. val greetStrings = new Array[String](3) var validUsers = for { val greetStrings = Array("Hello",”,”,” world!\n”) user <- newUserProfiles userName <- user get "userName" Access: greets(0) = "Hello" or greets.update(0, "Hello") name <- user get "name" greets(1) = ", " email <- user get "email" greets(2) = "world!\n" bio <- user get "bio" for (i <- 0 to 2) print(greets(i)) } yield new User(userName, name, email, bio) explode array TRY def max(values: Int*) = values.foreach(print) try { max(Array(1,2,3,4,5): _*) // ʻ:_*ʼ tell compiler to pass val f = new FileReader("input.txt") // Use and close file 12345 each elements } 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 FINALLY additionally add and remove elements from the beginning and end of the sequence. Used only to close opened resources. import scala.collection.mutable.ArrayBuffer val file = new FileReader("input.txt") val buf = new ArrayBuffer[Int]() try { buf += 1 // Use the file buf += 2 } finally { file.close() // Be sure to close the file } MATCH firstArg match { case "salt" => println("pepper") case "chips" => println("salsa") case "eggs" => println("bacon") case _ => println("huh?") } FOREACH (functional Style to print Main Args): args.foreach((arg: String) => println(arg)) args.foreach(arg => println(arg)) args.foreach(println)

[email protected] !! ! ! ! 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 { unnamed literals and then pass them around as values. private def filesHere = (new java.io.File(".")).listFiles filesMatching(_.endsWith(query)) Function literal (closure or open term): some Text var more = 10 def filesContaining(query: String) = (x: Type, y: Type) => x + y + more filesMatching(_.contains(query)) 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} } some Text increase: (Int) => Int = (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 = 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. someNumbers.foreach(println ) // all same result Build an XML def multiplier(i: Int)(factor: Int) = i * factor val simple = {3 + 4} knowing the function: val byFive = multiplier(5) _ res3: scala.xml.Elem = 7 def sum(a: Int, b: Int, c: Int) = a + b + c val byTen = multiplier(10) _ val xml = scala.xml.XML.loadString("evt") sum(1, 2, 3) xml: scala.xml.Elem = event res0: Int = 6 It’s possible to curry a function: val f = (x: Double, y: Double, z: Double) => x * y / z val a = sum _ CDATA val fc = f.curry val body = {PCData(in.getBodyasTxt)} 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) { res15: Int = 9 val year: Int 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 { val arr = Array("What's", "up", "doc?") writer.close() {description} echo(arr: _*) } {year} } {licence} 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" 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. def myWhile(conditional: => Boolean)(f: => Unit) { Scala’s parameterized types are similar to Java and C# if (conditional) { 1967 generics and C++ templates. HB-PNJ onInOut[+Ti, +To]( infoInput:Ti ): To f myWhile(conditional)(f) 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) { } println("still awesome") Implicit 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 {contents} => "It's an a: "+ contents Explicits-First Whenever code type checks as it is case {contents} => "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 {contents @ _*} => "It's an a: "+ contents notice the “@” is a pattern with a variable binding. [email protected]!! ! ! ! ! 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. val truthier: PartialFunction[Boolean, String] = { 1/ No needs to add new to create a class instance: Tuple Pattern 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) // def copy[T'](a: T' = this.a, b: Int = this.b): A[T'] = // The injection method (optional) case (id, p @ Person(_, _, _)) => // new A[T'](a, b) def apply(user: String, domain: String) = format("%s is underpaid.\n", p) } user +"@"+ domain case _ => val a1: A[Int] = A(1, 2) // The extraction method (mandatory) } val a2: A[String] = a1.copy(a = "someString") def unapply(str: String): Option[(String, String)] = { 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 val Decimal = new Regex("""(-)?(\d+)(\.\d*)?""") case Triangle(p1, p2, p3) => case class Get (body: String) extends HttpMethod // Or more simpler println("Triangle: point1 = "+p1+", point2 = case class Head (body: String) extends HttpMethod "+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 } case class Trace (body: String) extends HttpMethod Searching: 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 Option Type -1.0 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 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: 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 decimalpart: String = .23 case "hello" | “Ciao” => "hi!" val (number, string) = myTuple val Decimal(sign, integerpart, decimalpart) = "1.0" case i: Int => "scala.Int" number: Int = 123 string: java.lang.String = abc 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 { t } => 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 _ => } [email protected]!! ! ! ! ! 6 / 6!! ! ! ! ! ! v. 1.1