Scala Introduction

Post on 24-Jan-2015

174 views 7 download

description

A brief into into scala language concepts

transcript

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/