Towards Scala Certfications

by Stephane Micheloud, January 2011

[Home]
[Back]

In his article "Scala levels: beginner to expert, application programmer to library designer" Martin Odersky, creator of the language Scala, proposes a categorization of Scala skills with the intent to help teachers and book authors ([2]) to decide in which order to pick subjects to learn.

We expect Odersky's attempt to categorize Scala skills will very soon awake the interest of training companies offering certification courses and from software companies seeking for certified Scala developers.

We give here concrete examples for each skill level to support self-training and auto-evaluation. In the following we assume the reader already has a good knowledge of Java.

Level Application programmer Library designer
1
  • Java-like statements and expressions: standard operators, method calls, conditionals, loops, try/catch.
  • class, object, def, val, var, import, package
  • Infix notation for method calls (SLS 6.12)
  • Simple closures [1].
  • Collection classes with map, filter, etc. [2]
  • for-expressions (SLS 6.19)
  • Type parameters
  • Traits
  • Lazy vals
  • Control abstraction, currying
  • By-name parameters
2
  • Pattern matching (SLS Ch.8)
  • Trait composition
  • Recursion, in particular tail recursion
  • XML literals
  • Variance annotations
  • Existential types
  • Self type annotations and the cake pattern for dependency injection
  • Structural types (aka static duck typing)
  • Definition map/flatmap/withFilter for new kinds of for-expressions
  • Extractors
3
  • Fold operations, i.e. methods such as foldLeft, foldRight
  • Streams and other lazy data structures
  • Actors
  • Combinator parsers [4].
  • Early initializers (SLS 5.1.6)
  • Abstract types
  • Implicit definitions (SLS Ch.7) [3].
  • Higher-kinded types

Level 1 Examples

Anonymous functions []

Placeholder syntax Standard syntax
_ + 1 x => x + 1
_ * _ (x1, x2) => x1 * x2
(_: Int) * 2 (x: Int) => (x: Int) * 2
if (_: Boolean) x else y z => if (z) x else y
_.map(f) x => x.map(f)
_.map(_ + 1) x => x.map(y => y + 1)

Implicit views []

// File implicits.scala
class C(x: Int = 1) {
  def +(y: Int) = x + y
}
object C {
  implicit def intOps(x: Int) = new {
    def +(c: C) = c + x
  }
}
import C._
object implicits extends App {
  val c = new C()
  println(c + 3 + 2)
  println(3 + c + 2)
}

Level 2 Examples

Level 3 Examples

Combinator parsers []

import scala.util.parsing.combinator._

class Arith extends JavaTokenParsers {
  def expr: Parser[Any] = term~rep("+"~term | ""~term)
  def term: Parser[Any] = factor~rep("*"~factor | "/"~factor)
  def factor: Parser[Any] = floatingPointNumber | "("~expr~")"
}

object ArithTest extends Arith {
  def main(args: Array[String]) {
    println("input : "+args(0))
    println(parseAll(expr, args(0)))
  }
}

Quiz

  1. [A1] Which is the only modifier allowed in block-local definitions ?
  2. [L3] In which cases implicit conversions can be applied ? Give two examples for each case.
  3. [A2] Consider the following function definition:

    def f(x: Int, y: Int) = x match {
      case ‘y‘ => ...
    }

    What kind of pattern is 'y' ?

  4. [A2] A template may also start with a trait reference such as mt1 with ... with mtn. Give the list of parents of that template.
  5. [A2] What are the evaluation steps of the template A1 with B1 with C1 {stats} where A1<:A, B1<:B and C1<:C ?
  6. [A1] How does the Scala compiler interpret a Java class with static members ?
  7. [L3] Two objects a1 and a2 of type A are printed out to the console. We claim that the displayed values are respectively 1 and 2. Is it possible in Scala ? If not, explain why. Otherwise give the declarations of a1 and a2.

    class A {
      protected val n = 5
      override def toString = n.toString
    }
    // object a1 extends ...
    // println(a1)
  8. [A2] Can the result type of a recursive function definition be omitted in Scala ? If yes, give an example.

Answers

  1. implicit (SLS 6.25).
  2. Implicit conversions can be applied to expressions whose type does not match their expected type and to unapplied methods (SLS 6.26).

    Examples of case 1 are overloading resolution, type instantiation, numberic widening, numeric literal narrowing and value discarding (SLS 6.26.1).

    Examples of case 2 are method evaluation, implicit application, eta expansion, empty application (SLS 6.26.2).

  3. 'y' is a stable identifier pattern (SLS 8.1.5).
  4. Parents of template mt1 with ... with mtn are (supertype of mt1, mt1, ..., mtn) (SLS 5.1).

    class A
    trait A1 extends A; trait B1; trait C1
    
    object templates extends App {
      val c = new A1 with B1 with C1 getClass
    
      // prints "A"
      println(c.getSuperclass.getName)
      // prints "A1,B1,C1"
      println(c.getInterfaces map (_.getName) mkString ",")
    }
  5. Evaluation steps of template A1 with B1 with C1 {stats} are (C,B,A,A1,B1,C1,stats) where A1<:A, B1<:B and C1<:C (SLS 5.1, p.55).

    class C { print("C,") }
    class B extends C { print("B,") }
    class A extends B { print("A,") }
    
    trait A1 extends A { print("A1,") }
    trait B1 extends B { print("B1,") }
    trait C1 extends C { print("C1,") }
    
    object mixineval extends Application {
      // prints "C,B,A,A1,B1,C1,stats"
      new A1 with B1 with C1 { println("stats") }
    }
  6. The Scala compiler interprets a Java class C with static members as a pair of a Scala class that contains all instance members of C and a Scala object that contains all static members of C (SLS 5.4).
  7. Yes, it is possible using either early initializers (SLS 5.1.6) or type refinements (SLS 3.2.7).

    // File objectinits.scala
    class A {
      protected val n = 5
      override def toString = n.toString
    }
    object a1 extends { override val n = 1 } with A
    object a2 extends A with { override val n = 2 }
    
    object objectinits extends Application {
      println(new A())  // prints "5"
      println(a1)  // prints "1"
      println(a2)  // prints "2"
    }
  8. Yes, it is OK to leave out the result type of factorial in class C, even though the method is recursive.

    trait I
      def factorial(x: Int): Int
    }
    class C extends I
      def factorial(x: Int) = if (x == 0) 1 else x * factorial(x - 1)
    }
    A class member definition m that overrides some other function m' in a base class of C may leave out the return type, even if it is recursive (SLS 4.6.4).

References

  1. The Scala Language Specification (SLS), Version 2.8
    Martin Odersky, November 2010
  2. Scala for the Impatient
    Cay Horstmann, March 2012
    Safari Books (ISBN: 978-0-321-77409-5)

About the Author

Stephane's Picture
Stéphane Micheloud is a senior software engineer. He holds a Ph.D in computer science from EPFL and a M.Sc in computer science from ETHZ. At EPFL he worked on distributed programming and advanced compiler techniques and participated for over six years to the Scala project. Previously he was professor in computer science at HES-SO // Valais in Sierre, Switzerland.
[Top]

Other Articles