2. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
3. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
4. Java Architecture
HelloWorld.java
javac
HelloWorld.class
load class Java Virtual Machine
Java Class Garbage
Libraries Loader Collector
Bytecode Executor JIT
HotSpot
compiler
interpret execute
Native OS
5. Java as a Platform
HelloWorld.****
****c
HelloWorld.class
load class
Java Virtual Machine
Java Class Garbage
Libraries Loader Collector
...
7. Why JVM?
● Most popular VM in the world
● Multi-platform
● Free
● Mature
● Secure and reliable
● Fast
can outperform native code compiled with GCC
● Management and monitoring capabilities
● Has a specification
– multiple vendor and open source implementations
8. Why Scala?
● Object oriented and functional
● Statically typed
● High performance
● High interoperability with Java
● Advanced type system
● Advanced concurrency model
● Support for modularity and extensibility
● Built-in XML support
9. Java and Scala History
Java
Java 1.1
announced, 1997
first beta Java Java 1.5 Java 1.6
J. Gosling release 1.0 Java 1.2 Java 1.3 Java 1.4 (Tiger) (Mustang)
1991 1995 1996 1998 2000 2002 2004 2006
GJ
1999
work on
Scala
M. Odersky starts
1995 1999 2001 1.0 2003 2.0 2006
10. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
11. Hello Scala
object HelloWorld extends Application { ● object = singleton class
● optional semicolon
println("Hello, world!")
● def
} ● implicit public
● type after name, optional
object HelloWorld { ● generics using [ ]
def main(args: Array[String]) = Unit =
: ● unit = void
System.out.println("Hello, world!") ● calling into java.lang
library
} ● different constructor
syntax
12. Simple Greeting
def main(args:Array[String]) = {
immutable variable
val size = args.length type int inferred
println("Greeting " + size + " members:")
mutable variable
var greeting = "Hello " type String int is an object,
inferred alternative method
for (i <- 0 until args.length) {
invocation syntax
greeting += (args(i) + ",") Java-like
loop
} array element access
if (args.length > 0) greeting = greeting.substring(0, greeting.length – 1)
greeting += "!" if statement
println(greeting);
}
13. Simple Timer
object SimpleTimer { function type
def oncePerSecond(callback: () => unit) {
while (true) { callback(); Thread.sleep(1000) }
}
def timeFlies() {
println("time flies like an arrow...")
}
def main(args: Array[String]) {
functions are objects
oncePerSecond(timeFlies)
}
}
15. Better Greeting
def main(args:Array[String]) = {
val size = args.length
println("Greeting " + size + " members:")
var greeting = "Hello "
for (i <- 0 until args.length) {
greeting += (args(i) + ",")
args.foreach(arg => greeting += (arg + " "))
}
if (args.length > 0) greeting = greeting.substring(0, greeting.length – 1)
greeting += "!"
println(greeting);
}
16. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
17. Tuples
def divmod(x: int, y: int) = (x / y, x % y)
val z = divmod(x, y)
println("quotient: " + z._1 + ", rest: " + z._2)
The actual type of a tuple depends upon the number and of
elements it contains and the types of those elements.
The type of (99, "Luftballons") is Tuple2[Int, String].
The type of ('u', 'r', "the", 1, 4, "me") is
Tuple6[Char, Char, String, Int, Int, String]
18. Map
val treasureMap = new HashMap[Int, String]
treasureMap += 1 -> "Go to island."
treasureMap += 2 -> "Find big X on ground."
treasureMap += 3 -> "Dig."
println(treasureMap(2))
When we say 1 -> "Go to island.", we are actually calling a method named ->
on an Int with the value 1, and passing in a String with the value "Go to island."
This -> method, which you can invoke on any object in a Scala program,
returns a two-element tuple containing the key and value.
val romanNumeral = Map(1 -> "I", 2 -> "II",
3 -> "III", 4 -> "IV", 5 -> "V")
println(romanNumeral(4))
19. Comprehensions
val filesHere = (new java.io.File(".")).listFiles
for (
file <- filesHere;
if file.isFile; Types with no typing!
if file.getName.endsWith(".scala")
) println("Found " + file)
val names = "Ted Neward" :: "Neal Ford" :: "Scott Davis" :: "Venkat
Subramaniam" :: "David Geary" :: Nil
val longFirstNames = for {
name <- names
firstName = name.substring(0, name.indexOf(' '))
if firstName.length > 4
} yield firstName
20. Comprehensions defined
Example: for (val p ← persons; p.age > 20) yield p.name
Generally, a for-comprehension is of the form
for ( s ) yield e
s is a sequence of generators, definitions and filters
generator is of the form val x ← e,where e is a list-valued
expression; it binds x to successive values in the list
definition is of the form val x = e; it introduces x as a name
for the value of e in the rest of the comprehension
filter is an expression f of type boolean; it omits from
consideration all bindings for which f is false
22. Basic pattern matching
Scala case statements can’t “overlap” causing
multiple matches
Match statement returns whatever value is
returned from the matched case statement
23. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
24. Everything is an object
● Scala uses a pure object-oriented model
similar to Smalltalk: every value is an object
and every operation is a message send.
● Every class in Scala inherits from scala.Any
● The classes fall into two categories:
– value classes inherit from scala.AnyVal and
– reference classes inherit from scala.AnyRef
26. Null and Nothing
● Type Null is a subtype of all reference types; its
only instance is the null reference.
Since Null is not a subtype of value types, null is not a
member of any such type. For instance, it is not
possible to assign null to a variable of type int.
● Type Nothing is a subtype of every other type;
there exist no instances of this type.
For instance, the Scala library defines a value Nil of type
List[Nothing]. Because lists are covariant in Scala,
this makes Nil an instance of List[T], for any
element type T.
28. Simple property and
default constructor
Java: Scala:
public class Person { (var name: String)
class Person {
private String name = null; var name: String
public Person(String name) { }
this.name = name;
} ...
public String getName() { println(person.name)
return name;
}
public void setName(String name) {
this.name = name;
}
}
29. Constructors, operators,
overriding methods
class Rational(n:Int, d:Int) { Default
constructor
private def gcd(x:Int, y:Int): Int = {
...//greatest common denominator
} Object initialization uses
private val g = gcd(n,d) constructor properties,
read-only properties defined
val numer:Int = n/g
val denom:Int = d/g Alternative constructor;
def this(n:Int) = { this(n, 1) } must call the default constructor
def +(that:Rational) = new Rational(numer*that.denom + that.numer*denom,
denom * that.denom)
def -(that:Rational) = ... Operators
def *(that:Rational) = ... defined
def /(that:Rational) = ...
override def toString() = "Rational: [" + numer + " / " + denom + "]"
} Override method –
override modifier is mandatory
30. Abstract class
abstract class Shape {
var fillColor:Color = null Property
def draw(g:Graphics):Unit Abstract
methods
def area:Double
}
32. Advanced Properties
Effectively, all public variables are instance properties.
To override mutator and accessor behavior:
_= method suffix
syntax allows
to redefine the
assignment
operator for a
variable
33. Simulating a Java Bean
class Person(fn:String, ln:String, a:Int) {
@scala.reflect.BeanProperty var firstName = fn
@scala.reflect.BeanProperty var lastName = ln
@scala.reflect.BeanProperty var age = a
override def toString =
"[Person firstName:" + firstName + " lastName:"
+ lastName + " age:" + age + " ]"
}
34. More on Methods
● Protected and private, packages
– public by default
– protected and private modifiers supported
– private[<package name>] enhanced “package protected” -
applies to one of the containing packages of current method
● Returning from method
– return statement is optional: the last statement in an expression,
be it a scope, a closure or a method becomes its return value.
– If method can return at different points in the execution flow, return
type must be specified
● Repeated parameters (var-args) - <method>(...,<arg>*)
● Method reference
– call without parameters or prefix with &
35. Advanced Objects
● Singletons and companions
● Object as a function
● Case classes
● Sealed classes
● Traits and mix-in class composition
● Implicit conversions (views)
● More...
36. Singleton classes and
pseudo-static methods
● class vs. object (Singleton design pattern)
● companions
object Person { //companion module
def createPerson() = new Person()
}
class Person { //companion class
def name() = "Daniel"
}
37. Function Object
Function object has one or more apply methods:
object Square {
def apply(in: double) = in * in
def apply(in: float) = in * in
def apply(in: int) = in * in
} val xSquared = Square(x) Doug Pardee
Together with companion object feature, it is used to
facilitate the Factory Method design pattern, as we saw
in previous Map example:
val romanNumeral = Map(1 -> "I", 2 -> "II", 3 -> "III",
4 -> "IV", 5 -> "V")
38. ADTs Using Case Class
● Case classes export their constructor parameters and
provide a recursive decomposition mechanism via
pattern matching. The constructor parameters of
case classes are treated as public values and can be
accessed directly.
● The new keyword is optional for instance creation.
case class ClockTime (hour: Int, min: Int)
is a valid case class definition.
ClockTime(10,30) creates an instance.
It makes only sense to define case classes if pattern matching is
used to decompose data structures.
39. Case Class - Example
The output will look something like this:
Red: 100
Blue: 220
R: 100, G: 200, B: 50
Invalid color
40. Another Case Class
Set of definitions for binary tree:
In-order traversal of binary tree:
41. Case classes defined
● All lower-case identifiers in the pattern will bind the decomposed
value and are available on the right-hand side of the pattern.
● Order is important: a first-match policy is used.
● Constant values can be used in patterns to restrict matching case
ClockTime(10, min) will only match any time in the 10th hour (and
bind minutes to min)
● Richer conditions can be defined with guards.
– case ClockTime(hour, min) if hour > min
● When no pattern matches a value, the match statement throws a
MatchError.
● A default case can be added, using the wild-card pattern. case _ will
match any value.
42. Exception handling
Exception handling uses “almost Java” syntax with pattern match on
exception type within the catch clause.
Side note: Scala does not have checked exceptions, in contrast to Java.
43. Sealed classes
Sealed classes are defined using the sealed modifier.
A sealed class may not be directly inherited, except if the
inheriting template is defined in the same source file as
the inherited class*.
In case of pattern match on sealed class, the compilation
will emit warnings if the set of patterns is not exhaustive
(MatchError might be raised at run-time)
44. Traits and
Mixin Class Composition
● Trait is a special kind of class defined using trait keyword
● Traits are like Java interfaces, but can define default
implementations for methods in the trait. A class can
incorporate as many traits as desired using with
keyword, accumulating their implementations.
● A trait can be inherited
– when defining a class
class JamesBondsCar extends Car with Flying with Diving
– or when creating an instance
val jbsCar = new Car with Flying with Diving
46. Traits – more details
● There must be a common parent class with the
inherited
● When multiple traits are inherited
– they can refer to members of their common super class,
– but not to members of other mixed-in traits.
● A trait can require another class or trait; it can only be
mixed-in when the requirement is available.
trait Reading extends Person requires Seeing
trait Reading extends Person { self: Seeing => ... }
● In contrast to classes, traits may not have constructor
parameters.
47. Mixins
He who defs last, defs best
The order in which traits are mixed-in determines overriding strategy
“Expression problem” example:
trait Base { trait BasePlus extends Base {
type exp <: Exp; class Plus(l: exp, r: exp) extends Exp {
trait Exp { val left = l; val right = r;
def eval: int def eval = left.eval + right.eval
} }
class Num(v: int) extends Exp { }
val value = v; trait BaseNeg extends Base {
def eval = value class Neg(t: exp) extends Exp {
} val term = t;
} def eval = - term.eval;
}
}
trait Show extends Base { trait BasePlusNeg extends BasePlus with BaseNeg;
type exp <: Exp;
trait Exp extends super.Exp { trait ShowPlusNeg extends BasePlusNeg with Show {
def show: String; class Plus(l: exp, r: exp) extends
} super.Plus(l, r) with Exp {
class Num(v: int) extends def show = left.show + "+" + right.show;
super.Num(v) with Exp { }
def show = value.toString(); class Neg(t: exp) extends super.Neg(t) with Exp {
} def show = "-(" + term.show + ")";
} }
}
48. Traits – back to HelloWorld
object HelloWorld extends Application {
println("Hello, world!")
}
Surprise: Application is a trait!
● The main() method of the Application trait provides the ubiquitous entry point for
Java applications
● Since Application is a trait, the method actually "shows up" on the subclass
(HelloWorld).
● To execute this method, it is necessary to create the HelloWorld singleton, which
means constructing an instance of HelloWorld, which means "playing" the body of
the class, which effectively executes the application.
● Only after that is complete does the trait's main() get invoked
49. Implicit conversions (views)
Scala allows to define special methods which take a value
of a certain type (B) in as a parameter and return a value of
a different type (A) as the result. By marking this method
implicit, you tell the compiler to automatically use this
conversion in situations where a value of type A is called
for but a value of type B was passed.
implicit def str2int(str:String):Int = Integer.parseInt(str)
def addTwo(a:Int, b:Int) = a + b
addTwo("123", 456)
50. Implicit conversions -
usage example
Adding methods to classes.
Back to the loop we saw: for (i <- 0 until args.length) ...
=
val range = 0.until(args.length)
for (i <- range) ...
Where does method until come from?
scala.runtime.RichInt
How does 0:Int become a RichInt?
scala.Predef has
implicit def intWrapper(x:Int):RichInt = new RichInt(x)
51. Advanced classes and
methods
Packages and imports
Richer import syntax, import anywhere in the code
Implicit parameters
If implicit object of matching type is found “in scope” it can
replace a missing parameter
Inner classes and nested functions
inner classes are per instance, unlike in Java
Operators
any method can be used as infix operator
Currying
when a method is called with a fewer number of parameters, this will
yield a function taking the missing parameters as its arguments.
52. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
53. Generics
Scala Generics are erased after compilation, just like in Java.
abstract class TreeSet[A] { The contains and incl methods
def incl(x: A): TreeSet[A]; compare elements using methods < and >.
def contains(x: A): boolean; For an arbitrary type parameter we cannot
} guarantee it has these two methods.
We can enforce the comparability of a trait TreeSet[A <: Ordered[A]] {
type by demanding that it is a subtype def incl(x: A): TreeSet[A];
of Ordered trait. def contains(x: A): boolean;
}
In Java we need to do something like:
class TreeSet<T extends Comparable<? super T>>
A view bounded type parameter trait TreeSet[A <% Ordered[A]] {
clause [a <% T] only specifies that ...
the bounded type a must be }
convertible to the bound type T, using
an implicit conversion
54. Generics - Variance
Some Scala library collections are covariant (unlike Java)
Covariant sub-typing
class Stack[+a] { A covariant type parameter of a class may only appear in
covariant positions: values in the class, result types of
...
methods in the class, and type arguments to other covariant
} types, but not types of formal method parameters.
class Stack[+a] {
def push(x: a): Stack[a] =
^ covariant type parameter a
appears in contravariant position.
Using lower bounds, we can generalize the push method in Stack
class Stack[+a] {
def push[b >: a](x: b): Stack[b] = new NonEmptyStack(x, this)
Besides +, there is also a - prefix which indicates contra-variant subtyping.
object EmptyStack extends Stack[Nothing] { ... }
55. Advanced Generics
● Type variables abstract class Graph {
type Edge
type Node <: NodeIntf
● Self types abstract class NodeIntf {
def connectWith(node: Node): Edge
}
def nodes: List[Node]
def edges: List[Edge]
def addNode: Node
}
● Existential types (Java generics interoperability, wildcards)
T forSome {type Q}
Example: def m(x : T forSome {type T <: A}) = x is a
method that takes arguments that conform to T <: A, it can be
written also as def m(x: _ <: A) = x = Java's ? extends A
● Kinds - Generics of a Higher Kind (in progress)
56. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
57. Cool stuff:
Option and Either Monads
● Often a method needs to return either a value or nothing,
depending on various conditions (Haskell's Maybe)
● Option[A] is a sealed case class in the Scala core libraries
with 2 subclasses: Some(a:A) and None
● Either is another sealed case Either[A,B] with Left(a:A)
and Right(b:B) options
58. Cool stuff:
Structural types
● Structural typing offers the ability to reduce the scope of
polymorphism only over the subset of behaviors that need to be
common between the classes.
● Scala offers the benefit of both dynamic and statically typed
worlds through its implementation of structural typing - a compile
time checked duck typing.
59. Cool stuff:
Extractor objects
Paper: Matching Objects with Patterns
In Scala, patterns can be defined independently of case
classes. To this end, a method named unapply is
defined to yield a so-called extractor.
Extractor object:
object Twice {
def apply(x: Int): Int = x * 2
def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}
object TwiceTest extends Application {
val x = Twice(21)
x match { case Twice(n) => println(n) } // prints 21
}
60. Cool stuff -
Concurrency & Actors
Paper: Event-Based Programming without Inversion of Control
● Moore's law has changed, we don’t get the same increase in clock
frequency as we used to, instead, we get more cores.
● Solve the problem by (re)writing software to be concurrent.
● Actors (programming model borrowed from Erlang) implemented as a Scala
library implements Message-Passing Concurrency rather than Shared-State
Concurrency (the scheme adopted by C, Java, C# etc.) Actors have no shared state and
are communicating by sending and receiving messages which makes it possible to write
code that is deterministic and side-effect-free.
● Unlike Erlang VM (BEAM) where process is very lightweight, Scala actor is
either thread-based or event based. Former is limited in number, latter can
block its OS thread.
● Erlang is a functional language - data is immutable, in Scala programmer
needs to take care of that alone.
● Scala is statically typed, while Erlang is dynamic
● Erlang uses tail recursion all the time, while Scala uses traditional iterations
(tail recursion in JVM is problematic)
● Erlang has built-in code hot-swapping capabilities, the possibilities for hot-
swapping in Scala are limited because of static typing
from Jonas Boner and Yariv Sadan
61. More cool stuff
● XML processing – native XML
● Monads
● Partial functions (isDefinedAt)
● Lazy values (lazy)
● Annotations (@)
● Parser combinators library
● ...
62. In this presentation:
● Motivation and History
● Meet Scala
● Simple data structures and loops
● Objects
● Types and Generics
● Advanced topics
● Conclusions and references
64. The power of Scala
operator = method = function = object
Scala supports several programming
paradigms off the shelf...
Functional programming: Object-oriented programming:
Makes it easy to build Makes it easy to adapt and
interesting things from extend
simple parts, using complex systems, using
- higher-order functions, - subtyping and inheritance,
- algebraic types and - dynamic configurations,
pattern matching, - classes as partial abstractions.
- parametric polymorphism.
65. “Scalable language”
...and allows the programmer to extend it
with completely new paradigms.
Programmer can define language constructs
def While (p: => Boolean) (s: => Unit) {
if (p) { s ; While(p)(s) }
}
66. Nobody's perfect...
● Language specification constantly changing
● Lack of proper reflection support
(undocumented)
● Not enough/inadequate documentation for
beginners
● Lacking proper IDE support
● Too many ways to do one thing, multi-
paradigm language problem (as in C++,
Perl) - can Scala really scale on LoC?
68. References
● Scala for Java refugees (Daniel Spiewak)
● The busy Java developer's guide to Scala (Ted Neward)
● Ricky Clarkson, David R. MacIver, Henrik Huttunen, Debasish Ghosh
● A tour of Scala and other resources on http://www.scala-lang.org/
● http://scala-blogs.org/
● Scala forums @ Nabble
● Scalazine @ Artima
● Programming in Scala (book) (M. Odersky, L. Spoon, B. Venners)
● Martin Odersky's Weblog
● The Scala Experiment (video) , JavaOne 2008 Scala (audio and slides)
● Scala APIs