scala introduction
DESCRIPTION
A brief into into scala language conceptsTRANSCRIPT
Scala Introduction
Constantine Nosovsky
Agenda
Motivation Imperative vs Functional What is Scala?
Scala syntax intro Case classes, tail recursion Putting it all together Pure functional theory implementation Collections
Advanced topics Resources
Motivation
Top “Scala” queries for the past 12 monthsGoogle trends (http://www.google.com/trends/)
Imperative vs Functional
Imperative– Mutable variables– Assignments– Control structures (if-else, loops, break, continue, return)– Sequence of instructions executed one-by-one
– Strong correspondence to the computer components
Imperative vs Functional
Functional– Immutable variables– Functions are treated as a first-class data types– Production, consumption and composition of functions
– Corresponds to math theory where data, operations and relationships are described, e.g. Matrix theory
Functional programming benefits
Better programming abstraction: combine complex operations by composing primitives
Looser coupling: no side effects only input and output parameters => better contract conformation
Better scalability: immutable (therefore thread-safe) objects
What is Scala?
Designed by Martin Odersky, 2003 Multi-paradigm: Functional and Imperative Object oriented
– Even primitive types are objects– Singleton objects instead of static methods and fields
Platform: JVM, LLVM Compatible with Java
Scala syntax intro: value declaration
Static strong inferred typing
val a: Int = 5
is similar to
val a = 5 // type will be inferred
Scala syntax intro: final
Subsequent assignment are not allowed
val a: Int = 5a = 10 // error: reassignment to val
var a: Int = 5a = 10 // OK for var, avoid using vars!
Scala syntax intro: method, expression
Expressions instead of statements
def abs(x: Int): Int = if (x >= 0) x else –x
Or even
val result = { if(f(x)) x else -x } * 2
Scala syntax intro: high-order functions
Functions might be passed as parameters
def map(xs: List[Int], m: Int => Int): List[Int] = if(xs.isEmpty) List() else List(m(xs.head)) ++ map(xs.tail, m)
// pass function as a parameterdef square(x: Int) = x * xmap(List(1, 2, 3), square)map(List(1, 2, 3), x => x * x)
Scala syntax intro: classes
class Class { def method = println("Class") } new Class().method // singleton object instead of static method object Singleton { def method = println("Singleton") } Singleton.method
Scala syntax intro: traits
Trait is similar to interface, but may contain implementation
trait Drawable { def draw() }trait Cowboy extends Drawable { override def draw() = println("Bang!")} trait Artist extends Drawable { override def draw() = println("A painting")}class CowboyArtist extends Cowboy with Artist// "A painting" will be used
Scala syntax intro: operators
Easy to build DSL
class Complex { def add(y: Complex) = ??? def +(y: Complex) = add(y) def unary_- = ???}val x = new Complex(); val y = new Complex()
x.add(y); x add y; x.+(y); x + y // equivalent-x // unary operator
Case classes and pattern matching
// class applicable for pattern-matchingcase class Complex(r: Int, i: Int)
// implicitly generated companion factory classval v = Complex(1, 2); val v2 = Complex(2, 3) // match object value and constructor argumentsv match { case Complex(r, _) => println("Real " + r) case null => println("No value")}
Recursion
Recursion is often used for list processing
def sum(xs: List[Int]): Int = if(xs.isEmpty) 0 else xs.head + sum(xs.tail) Problem: list of 1 million elements causes stack overflow
Tail recursion
If a function calls itself as its last action, the function’s stack frame can be reused
def sum(xs: List[Int]): Int = { // will be compiled to a loop in byte code @tailrec def loop(acc: Int, xs: List[Int]): Int = if(xs.isEmpty) 0 else loop(acc + xs.head, xs.tail)
loop(0, xs)}
Putting it all together
No mutable data sharing problem– Variables are final by nature– Classes are designed to be immutable
Easy composition – Everything is an expression returning result– Mixing functions, methods and operators– No side effects, i/o parameters only– Closure
Advanced type safety– Inferred: automatic deduction of the data type
OOP– Singleton classes instead of static methods/fields– Primitive types are objects as well– Traits for abstraction and multiple inheritance– Case classes and pattern matching
Pure functional theory implementation
Build a Set theory
Operations– Check whether an element belongs to a set– Union, Intersection, Difference– Filter set elements with a predicate
Sets are immutable, each modification produces a new set Functional way: no data structures, only rules
Pure functional theory implementation
// Set is a function checking element presencetype Set = Int => Boolean
def contains(s: Set, elem: Int): Boolean = s(elem)
// Returns the set of the one given elementdef singletonSet(elem: Int): Set = (x: Int) => x == elem
Pure functional theory implementation
Union, intersect, diff operations
def union(s: Set, t: Set): Set = (x: Int) => s(x) || t(x)
def intersect(s: Set, t: Set): Set = (x: Int) => s(x) && t(x)
def diff(s: Set, t: Set): Set = (x: Int) => s(x) && !t(x)
Pure functional theory implementation
Filter elements
// Returns the subset of s for which p holdsdef filter(s: Set, p: Int => Boolean): Set = intersect(s, p)
Pure functional theory implementation
Usage example
val oddNumbers = (x: Int) => x % 2 == 1val range = (x: Int) => x > 0 && x < 100 filter(range, oddNumbers)
Collections
Mostly immutable data structures Modifications will create a new instance Optimized for language structures
– Functional way of processing and construction– Pattern matching– For expressions
Collections: List
scala.collection.immutable.List Linked list implementation
Case class, has a factoryval list = List(1, 2, 3)
Prepending element will create a new list (shallow copy)val newList = 0 :: list
Collections: List
Methods head and tail used for one by one processing def contains(l: List[Int], e: Int): Boolean = if(l.isEmpty) false else l.head == e || contains(l.tail, e)
Applicable for pattern matching
def contains(l: List[Int], e: Int): Boolean = l match { case List() => false case head :: tail => head == e || contains(tail, e) }
Collections: Vector
Faster access by index than linked list Supports almost similar operations Hierarchical data structure
– Array of 32 elements– After all elements are filled becomes an array of 32 references to arrays of
elements– Then next level, again and again
elements elements … elements
references … references
references
Collections: common methods
exists, forall – contains by predicate
zip, unzip – transform two collection into a single one chaining corresponding items into a tuple
map, flatMap – apply transformation to each element
to[List, Map, Set, Stream]
sum, product, max, min
Advanced topics
OOP in Scala:– Traits– Generics, bounding– Subtyping (Any, Nothing)– Polymorphism
Language structures– For expressions– Lazy evaluation– Currying– Implicit parameters– Tuples
Concurrency Scala frameworks: akka, play
Resources
Coursera class by Martin Oderskyhttps://class.coursera.org/progfun-004
Scala API documentationhttp://www.scala-lang.org/api/current
Programming in ScalaMartin Odersky, Lex Spoon, Bill Venners. 2nd ed. Artima 2010
Scala tutorial by Twitterhttp://twitter.github.io/scala_school/