Sunday, March 9, 2014

Scala Crib Sheet #1


Yield-syntax

"Here is a function that identifies the .scala files and stores them in an array:

def scalaFiles = 
    for {
        file <- filesHere
        if file.getName.endsWith(".scala")
    } yield file

"Each time the body of the for expression executes it produces one value, in this case simply file. When the for expression completes, the result will include all of the yielded values contained in a single collection. The type of the resulting collection is based on the kind of collections processed in the iteration clauses. In this case the result is an Array[File], because filesHere is an array and the type of the yielded expression is File." [1]

Sealed

"When you write a pattern match, you need to make sure you have covered all of the possible cases. Sometimes you can do this by adding a default case at the end of the match, but that only applies if there is a sensible default behaviour... The alternative is to make the superclass of your classes sealed. A sealed class cannot have any new subclasses added except the ones in the same file."

Repeated Parameters (eg, def echo(args: String*)) "Scala allows you to indicate that the last parameter to a function may be repeated. This allows clients to pass variable length argument lists to the function". Appears to be equivalent to ellipses in Java.

Covariance and Contravariance 

"Whenever you write the function A=>B, Scala expands this to Function1[A,B]... the Function1 trait is contravariant in the function argument type S and covariant in the result type T as show:

trait Function1[-S, +T] {
  def apply(x: S): T
}

See here for an explanation of how contravariance and covariance work when overriding methods in Java.

Implicit

"The compiler first tries to compile it as is, bit it sees a type error. Before giving up, it looks for an implicit conversion that can repair the problem.. it tries the conversion method , sees that it works, and moves on...

"Only definitions marked implicit are available.

"An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion.

"Only one implicit is tried... For sanity's sake, the compiler does not insert further implicit conversions when it is already in the middle of trying another implicit... It's possible to circumvent this restriction.

"Whenever code type checks as it is written, no implicits are attempted. The compiler will not change code that already works.

self => 

"Sometimes it’s useful for a trait to be able to use the fields or methods of a class it is mixed in to, this can be done by specifying a self type for the trait. A self type can be specified for a class or a trait as follows:

trait SpellChecker { self =>

"... The syntax can be extended to specify a lower-bounds ...

trait SpellChecker { self: RandomAccessSeq[char] =>
  ...
}

"The compiler will check that any class in a hierarchy including SpellChecker is or extends RandomAccessSeq[char], so SpellChecker can now use the fields or methods of RandomAccessSeq[char]." [2]

@specialized

Using the class version of primitives can be expensive in JVMs so Scala allows this annotation to make things more efficient. It does this by generating more than one class - one for the Object implementation and one for the primitive [3].

This was added in Scala 2.8 and isn't to be found in Odersky's Programming in Scala book.


[1] Programming in Scala - Odersky
[2] Scala: Traits and Self Types - Mark Thomas
[3] Specializing for Primitive Types - Scala Notes

No comments:

Post a Comment