150x Filetype PDF File size 2.38 MB Source: homepage.cs.uiowa.edu
Symbolics Operators Import -> Returns a two-element Map( 1 -> "A", 2 -> "B") +, -, *, /, % Arithmetics import java.awt._ // All classes under java.awt tuple containing the key >, < ,<=, >=, ==, != Relational import java.io.File and value (1).->(“A”) import java.io.File._ // Import all Fileʼ static methods _ A placeholder, used in import com.xtech._ &&, ||, ! Logical import java.util.{Map, HashMap} // only the 2 classes imports, function literals, case _ => value.toString &, |, ^, ~ Bitwise Narrow import: etc. numbers.filter(_ < 0) (and, or, xor, inv) def doIt() = { : Separator between def add(i: Int): Int = ... <<, >>, >>> Bitwise shift import java.math.BigDecimal.{ONE} identifiers and type (left, right, unsigned right) println(ONE) annotations. The operator “==” check the value equality on } = Assignment. val one = “1” reference AND primitive type. Rename import: import java.math.BigDecimal.{ => Used in function literals numbers.filter(x => x < 0) ONE => _, ## // Exclude ONE to separate the argument Rich Operation ZERO => JAVAZERO # // Rename it ! list from the function Scala provides “rich wrapper” around basic types via implicit } body. conversions. println(JAVAZERO) <- 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) 0 min 5 0 import _root_.scala.collectionsjcl._ of)Used in parameterized -2.7 abs 2.7 Packages and abstract type declarations to constrain -2.7 round -3L File names don’t have to match the type names, the allowed types. 1.5 isInfinity false the package structure does not have to match the <% View bounds( apply def m [A <% B](args): R (1.0 / 0) isInfinity true directory structure. So, you can define packages in 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) Literals package com{ 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 = ... val long = 31L Long (“l” or “L”) Are immutable and can contain different types of elements. another type val nena = (99, "Luftballons",”1983”) @ Marks an annotation. @deprecated def bad() = val little: Short = 367 Short println(nena._1) ʻ Symbol val s = 'aSymbol val littler: Byte = 38 Byte println(nena._2) .... println(nena(0)) (not same Type in list) def doIt(r: Symbol) Floating point doIt(s); print(s.name) val double = 1.2345 Double _ Usage Summary If a method takes 0 or one parameter you can drop val e = 1.234e4 Double (“e” or “E”) Curried functions 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)) Character and String twice(_ + 1) (5) Variables val aChar = ʻDʼ Char res8: Double = 7.0 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!" \n line feed (\u000A) res4: Boolean = true Lazy initialization \b backspace (\u0008) same as: (only on Immutable) .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) Basic Types \” double quote (\u0022) Partially applied functions \’ single quote (\u0027) def sum(a: Int, b: Int, c: Int) = a + b + c Value Type Range 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) Short 16-bit signed two’s complement integer Boolean b: (Int) => Int = 15 15 val bool = true Boolean (true | false) (-2 to 2 - 1, inclusive) b(2) Int 32-bit signed two’s complement integer Check res10: Int = 6 31 31 (-2 to 2 - 1, inclusive) “abc”.isInstanceOf[String] Import statements Long 64-bit signed two’s complement integer re0: Boolean = true import com.xtech.cf._ 63 63 (-2 to 2 - 1, inclusive) Cast Char 16-bit unsigned Unicode character Match expressions 16 (0 to 2 - 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 classOf[String] Boolean true or false res7: java.lang.Class[String] = class java.lang.String Setter 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 “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 for (i <- 1 to 5) { “T >: Cat” or “-T” : (as T is superType of Cat) println("Do it!") AnyVal AnyRef 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 } All java.* All scala.* extending it. To Start it: Boolean Float ref. types ref. types Definition SimpleActor.start() trait Saxo { To start a thread immediately use the utility method actor: def play() { import scala.actors._ println("Nice sound!") val seriousActor2 = actor { } for (i <- 1 to 5) Helper for type Null } println("Do it!.") inference Extends } Nothing class Alto extends Saxo { Send message to Actor; override def toString = "Alto" import scala.actors._ Definition } val echoActor = actor { Simple class: class Instrument With while (true) { class ChecksumAccumulator { receive { private var sum = 0 class Baryton extends Instrument { case msg => println("received message: "+ msg) def add(b: Byte): Unit = sum += b override def toString = "Baryton" } } } 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 } val numer: Int = n Mixing res7: Any = TIMEOUT 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 Run it on the main Thread } a mixin.Traits are a way to inherit from multiple class-like trait SingleThread extends Actor{ constructs, but they differ in important ways from the 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 Getter / Setter classes and traits that are mixed into a class. } Linearization algorithm Run all actors in the Main thread: Once a val or var is defined within a class the corresponding 1 Put the actual type of the instance as the first element. Scheduler.impl = new SingleThreadScheduler accessor methods are generated. The generated methods 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 To generate JavaBean getter and setter add the annotation: its linearization to the cumulative linearization. (Ignore challenging, but pays off in performance. Because react @scala.reflect.BeanProperty var level: Int = _ ScalaObject, AnyRef, and Any for now.) does not return, the calling actor’s call stack can be discarded, freeing up the thread’s resources for a different Abstract 3 Working from left to right, remove any type if it actor. At the extreme, if all of the actors of a program use abstract class Document { appears again to the right of the current position. react, then they can be implemented on a single thread. def footNotes: Array[String] // abstract method 4 Append ScalaObject, AnyRef, and Any. As empiric rule: var nbOfPages : Int // abstract Field - Actors that are message-heavy are better implemented class C1 {def m = List("C1")} with “while(true)/receive” (Hogging a thread). type paper# // abstract type trait T1 extends C1 {override def m ={ "T1" :: super.m}} - Actors with non trivial work are better implemented with } trait T2 extends C1 {override def m ={ "T2" :: super.m}} “loop/react”. trait T3 extends C1 {override def m ={ "T3" :: super.m}} object NameResolver extends Actor { Inheritance class C2 extends T2 {override def m ={ "C2" :: super.m}} import java.net.{InetAddress, UnknownHostException} class A extends B class C extends C2 with T1 with T2 with T3{ def act() { Call super constructor override def m ={ "C" :: super.m} react { 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 } There is no static in Scala, instead use the companion 5 C, T3, C1, T2, C1, T1, C1, + C2 } object to support class-level operation and properties. A C2, T2, C1 def getIp(name: String): Option[InetAddress] = { companion is a singleton 6 C, T3, T2, T1, C2, T2, C1 - duplicates C1 but last try { class Book private (title: String) 7 C, T3, T1, C2, T2, C1 - duplicates T2 but last Some(InetAddress.getByName(name)) object Book { 8 C, T3, T1, C2, T2, C1, done. val favorites= """"Java Puzzlers", "Design Patterns"""" ScalaObject, AnyRef, Any }catch { 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 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] = FFrorom m TTraraveversarsabbllee ttraraiitt:: ! 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] = truth.isEmpty false ! Map(1 -> x, 3 -> x, 4 -> x) Map Set Seq List.unzip(zippedTruth) (List(0, 1, 2), Enumeration List(Fly, is, fun)) SortedMap SortedSet BitSet Buffer Vector LinearSeq object Color extends Enumeration { List.flatten( List(f, l, y, .) 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 Enumeration with value: truth.drop(2) List(fun) mutable and immutable variations of sequences (Seq), sets, object Direction extends Enumeration { truth.exists(s => s == "is") true and maps. Sequences are ordered collections, such as val Up = Value("goUp") arrays and lists. Sets contain at most one of each object, as 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) truth.length 3 import scala.collection.JavaConversions._ res1: Direction.Value = goDown truth.map(s => s + "!") List(Fly!, is!, fun!) Sets and Maps Lists truth.mkString(",") Fly,is,fun Immutable Set (default if no explicit import): Class List provides fast access to the head of the list, but truth.remove(s => s.length == 3) List(is) var jetSet = Set("Boeing", "Airbus") not the end. Thus, when you need to build a list by truth.reverse List(fun, is, Fly) jetSet += "Lear" appending to the end, you should consider building the list truth.sort((s,t) List(fun, Fly, is) backwards by prepending elements to the front, then when => s.charAt(0).toLowerCase println(jetSet.contains("Cessna")) you’re done, calling reverse to get the elements in the order Mutable Set: you need. < t.charAt(0).toLowerCase) import scala.collection.mutable.Set Another alternative, which avoids the reverse operation, is truth.indices List(0, 1, 2) val movieSet = Set("Hitch", "Poltergeist") to use a ListBuffer (see next section) 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)) Immutable Map (default if no explicit import): val threeFour = List(3, 4) truth find (_.charAt(0) == 'a') None import scala.collection.immutable.HashMap val oneTwoThree = "one" :: "two" :: "three" :: Nil 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) Mutable Map: (_.charAt(0).toLowerCase != 'i') 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.") Basics: truth.reduceRight (_ + _) Flyisfun treasureMap += (3 -> "Dig.") val nums = Set(1, 2, 3) truth.foldRight(List[String]()) List( , , ) println(treasureMap(2)) nums + 5 Set(1, 2, 3, 5) {(x, list) => ("<"+x+">") :: list} Conversion immutable to mutable nums - 3 Set(1, 2) truth.foldLeft("Yes,")(_ + _) Yes,Flyisfun import scala.collection.mutable nums ++ List(5, 6) Set(1, 2, 3, 5, 6) List(1,2,3) reduceLeft(_ + _) 6 var mutaSet = mutable.Set.empty ++ immutableSet nums -- List(1, 2) Set(3) List.range(9, 1, -3) List[Int] = List(9, 6, 3) Conversion mutable to immutable nums & Set(1, 3, 5, 7) Set(1, 3) List.make(5, 'a') List(a, a, a, a, a) val immu = Map.empty ++ muta nums.size 3 List.concat( List(b, c) Map sample nums.contains(2) TRUE List(), List('b'), List('c')) FFrorom m IItteerarabbllee ttraraiitts:s: 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) words += "thx" Set(thx) (fun,2) ) nums ++ Map(i -> 1, ii -> 2, iii -> 3, v -> 5) 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), nums.size 2 words --= List("α", "β") Set(!) List(fun) nums.contains("ii") true words.clear Set() truth.sliding(2) Iterator: List(Fly, is), nums("ii") 2 List(is, fun) 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 nums.values Iterator over the integers 1 and 2 general remark of Lists) and to avoid stack overflow. nums.isEmpty false val buf = new ListBuffer[Int] buf += 1 Mutable buf += 2 val wd = scala.collection.mutable.Map.empty[String, Int] 3 +: buf wd += ("one" -> 1) Map(one -> 1) buf.toList wd -= "one" Map() List[Int] = List(3, 1, 2) 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: Immutable if, while, for, try, match 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 FILTERING scala.collection.mutable.Queue[String] = Queue(a, b, c) for ( file <- filesHere queue.dequeue if file.isFile; res0: String = a if file.getName.endsWith(".scala") queue ) println(file) res1: scala.collection.mutable.Queue[String] = Queue(b, c) Stacks If you add more than one filter on a generator, the Mutable and immutable last-in-first-out sequence. filter’s if clauses must be separated by semicolons. This is why there’s a semicolon after the Mutable “if file.isFile” 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) def grep(pattern: String) = stack.top for ( res0: Int = 2 file <- filesHere stack if file.getName.endsWith(".scala"); // <-- semi-colon res1: scala.collection.mutable.Stack[Int] = Stack(1, 2) 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: Creation: for clauses yield body 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 Access: userName # <- user get "userName" 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 { TRY def max(values: Int*) = values.foreach(print) val f = new FileReader("input.txt") // Use and close file max(Array(1,2,3,4,5): _*) // ʻ:_*ʼ tell compiler to pass } catch { 12345 each elements case ex: FileNotFoundException => // missing file ArrayBuffer case ex: IOException => // Handle other I/O error } 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 } firstArg match { 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
no reviews yet
Please Login to review.