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 |
|
|
2 |
|
|
3 |
|
|
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) }
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))) } }
[A2] Consider the following function definition:
def f(x: Int, y: Int) = x match { case ‘y‘ => ... }
What kind of pattern is 'y'
?
mt1 with
...
with mtn
. Give the
list of parents of that template.
A1 with B1 with C1 {stats}
where
A1<:A
, B1<:B
and C1<:C
?
[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)
implicit
(SLS 6.25).
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).
'y'
is a stable identifier pattern (SLS 8.1.5).
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 ",") }
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") } }
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).
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" }
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) }
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).