博文

目前显示的是 六月, 2014的博文

Scala For-Comprehensions

A for-comprehension is syntactic sugar for map, flatMap and filter operations on collections. The general form is for (s) yield e s is a sequence of generators and filters p <- e is a generator if f is a filter If there are several generators (equivalent of a nested loop), the last generator varies faster than the first You can use { s } instead of ( s ) if you want to use multiple lines without requiring semicolons e is an element of the resulting collection Example 1 // list all combinations of numbers x and y where x is drawn from // 1 to M and y is drawn from 1 to N for (x <- 1 to M; y <- 1 to N) yield (x,y) is equivalent to (1 to M) flatMap (x => (1 to N) map (y => (x, y))) Translation Rules A for-expression looks like a traditional for loop but works differently internally for (x <- e1) yield e2 is translated to e1.map(x => e2) for (x <- e1 if f) yield e2 is translated to for (x <- e1.filter(x => f)) yield e2 for (x <- e1...

Scala Collections

Base Classes Iterable (collections you can iterate on) Seq (ordered sequences) Set Map (lookup data structure) Immutable Collections List (linked list, provides fast sequential access) Stream (same as List, except that the tail is evaluated only on demand) Vector (array-like type, implemented as tree of blocks, provides fast random access) Range (ordered sequence of integers with equal spacing) String (Java type, implicitly converted to a character sequence, so you can treat every string like a Seq[Char]) Map (collection that maps keys to values) Set (collection without duplicate elements) Mutable Collections Array (Scala arrays are native JVM arrays at runtime, therefore they are very performant) Scala also has mutable maps and sets; these should only be used if there are performance issues with immutable types Examples val fruitList = List("apples", "oranges", "pears") // Alternative syntax for lists val fruit = "apples...

Scala Pattern Matching & Options

Pattern Matching Pattern matching is used for decomposing data structures: unknownObject match { case MyClass(n) => ... case MyClass2(a, b) => ... } Here are a few example patterns (someList: List[T]) match { case Nil => ... // empty list case x :: Nil => ... // list with only one element case List(x) => ... // same as above case x :: xs => ... // a list with at least one element. x is bound to the head, // xs to the tail. xs could be Nil or some other list. case 1 :: 2 :: cs => ... // lists that starts with 1 and then 2 case (x, y) :: ps => ... // a list where the head element is a pair case _ => ... // default case if none of the above matches } The last second example shows that every pattern consists of sub-patterns: it only matches lists with at least one element, where that element is a pair. x and y are again patterns that could match only specific types. Options ...

Scala Type Parameters & Variance

Type Parameters Similar to C++ templates or Java generics. These can apply to classes, traits or functions. class MyClass[T](arg1: T) { ... } new MyClass[Int](1) new MyClass(1) // the type is being inferred, i.e. determined based on the value arguments It is possible to restrict the type being used, e.g. def myFct[T <: TopLevel](arg: T): T = { ... } // T must derive from TopLevel or be TopLevel def myFct[T >: Level1](arg: T): T = { ... } // T must be a supertype of Level1 def myFct[T >: Level1 <: TopLevel](arg: T): T = { ... } Variance Given A <: B If C[A] <: C[B], C is covariant If C[A] >: C[B], C is contravariant Otherwise C is nonvariant class C[+A] { ... } // C is covariant class C[-A] { ... } // C is contravariant class C[A] { ... } // C is nonvariant For a function, if A2 <: A1 and B1 <: B2, then A1 => B1 <: A2 => B2. Functions must be contravariant in their argument types and covariant in their result types, e.g. t...

Scala Operators

Operators myObject myMethod 1 is the same as calling myObject.myMethod(1) Operator (i.e. function) names can be alphanumeric, symbolic (e.g. x1, *, +?%&, vector_++, counter_=) The associativity of an operator is determined by its last character: Right-associative if ending with :, Left-associative otherwise. assignment operators have lowest precedence.

Scala Classes

Classes class MyClass(x: Int, y: Int) { // Defines a new type MyClass with a constructor require(y > 0, "y must be positive") // precondition, triggering an IllegalArgumentException if not met def this (x: Int) = { ... } // auxiliary constructor def nb1 = x // public method computed every time it is called def nb2 = y private def test(a: Int): Int = { ... } // private method val nb3 = x + y // computed only once override def toString = // overridden method member1 + ", " + member2 } new MyClass(1, 2) // creates a new object of type this references the current object, assert(<condition>) issues AssertionError if condition is not met. See scala.Predef for require , assume and assert . Class hierarchies abstract class TopLevel { // abstract class def method1(x: Int): Int // abstract method def meth...

Scala Higher order functions & Currying

Higher order functions These are functions that take a function as a parameter or return functions. // sum() returns a function that takes two integers and returns an integer def sum(f: Int => Int): (Int, Int) => Int = { def sumf(a: Int, b: Int): Int = {...} sumf } // same as above. Its type is (Int => Int) => (Int, Int) => Int def sum(f: Int => Int)(a: Int, b: Int): Int = { ... } // Called like this sum((x: Int) => x * x * x) // Anonymous function, i.e. does not have a name sum(x => x * x * x) // Same anonymous function with type inferred def cube(x: Int) = x * x * x sum(x => x * x * x)(1, 10) // sum of cubes from 1 to 10 sum(cube)(1, 10) // same as above Currying Converting a function with multiple arguments into a function with a single argument that returns another function. def f(a: Int, b: Int): Int // uncurried version (type is (Int, Int) => Int) def f(a: Int)(b: Int): Int // c...

Scala Evaluation Rules

Evaluation Rules Call by value: evaluates the function arguments before calling the function Call by name: evaluates the function first, and then evaluates the arguments if need be def example = 2 //  method? evaluated when called val example = 2 // evaluated immediately lazy val example = 2 // evaluated once when needed def square(x: Double) // call by value def square(x: => Double) // call by name def myFct(bindings: Int*) { ... } // bindings is a sequence of int, containing a varying #of arguments