Sunteți pe pagina 1din 6

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 >, < ,<=, >=, ==, != Relational import java.io.File._ // Import all Fileʼ static methods
(1).->(“A”)
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
generator expressions.
Code Result create an absolute path, start with _root_
0 max 5 5
<: Upper bounds (a subtype def apply[T <: U](x: T) import _root_.scala.collectionsjcl._
0 min 5 0
of)Used in parameterized
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(r: 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
val e = 1.234e4 Double (“e” or “E”) Curried functions
If a method takes 0 or one parameter you can drop
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!" class Marshaller[T] { def marshall(t:T) = {println(t)} }
val s = “”” itʼs “you” “”” Raw String ( It’s “you” )
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)
lazy val x = { println("initializing x"); "done" } Function literals
\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, c: 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 = <function>
(-27 to 27 - 1, inclusive) val b = sum(1, _: Int, 3)
Boolean
Short 16-bit signed two’s complement integer b: (Int) => Int = <function>
(-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
re0: Boolean = true import com.xtech.cf._
(-263 to 263 - 1, inclusive)
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 var age: Int = _ // age initialized to 0
Double 64-bit IEEE 754 double-precision float
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 }
nicolas.jorand@crossing-tech.com!! ! ! ! ! 1 / 6! ! ! ! ! ! ! v. 1.1
Class Hierachy Variance Actors
Covariance: Ability to accept sub-classes. import scala.actors._
Any object SimpleActor extends Actor {
“T <: Pet” or “+T” : (as T extends Pet)
Equivalent to
java.long.Object def act() {
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.
Boolean Float
All java.*
ref. types
All scala.*
ref. types
To Start it:
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 }
inference
Null 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 }
} To send a message:
Ordered Traits echoActor ! “Hello”
Constructor 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 }
val numer: Int = n res7: Any = TIMEOUT
val denom: Int = d
Mixing
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).
type paper# // abstract type - 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 {
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 1C + 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", "Design Patterns"""" case _:UnknownHostException => None
SelfType }
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

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)

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)

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(&quot;Hello&quot;)</script>
<script type="javascript">
numbers.filter(_ > 0) Currying document.write(&quot;world!&quot;)</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

S-ar putea să vă placă și