scala en

66
Sca la František Kocun

Upload: fero-kocun

Post on 10-May-2015

2.718 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Scala en

Scala

František Kocun

Page 2: Scala en

“I can honestly say if someone had shown me the Programming in Scala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy.“

James Strachan, Groovy creator

Page 3: Scala en

“No other language on the JVM seems as capable of being a "replacement for Java" as Scala, and the momentum behind Scala is now unquestionable.“

Charles Nutter, JRuby core developer

Page 4: Scala en

“Scala.“James Gosling, Java creator

Answer on a question, which language would he use now on JVM except Java.

Page 5: Scala en

“On my radar, the current best exit strategy for Java is Scala.„

Bruce Eckel, author of many books

Page 6: Scala en

Scala vs Java

Scala removes• break, continue, goto• static• primitive types• raw types (every type parameter „generics“ has to be

stated)• operators (all are methods)• override is not more optional

(when overriding in Scala one has to declare override)

Page 7: Scala en

Scala vs Ruby and Groovy• Scala has two type of fans

– Java programmers (pros of functional programming)– Ruby programmers (pros of language with static typing)

• Implicits, structural typing and type inference, resembles work with language with dynamic typing

• Scala is compiles a compiled language and all types are checked in compilation time– one can not call a non existing method– no ClassCastException in runtime– possibility to refactor– as fast as Java

Page 8: Scala en

Scala unifies FP and OOP

Page 9: Scala en

Why to unify FP and OOP

Functional

• Abstraction– Functions– Higher-order functions– Parametric

polymorphism

Object-oriented

• Extending, state dependent behavior– Inheritance– Polymorphism– Encapsulation– Dynamic configuration

Both approaches are complementary

Page 10: Scala en

Where?

• Manipulation of data structures – collections, trees, ADTs, ...

• Internal/External DSLs– OSGi, Apache Camel, scala-query,

specs, built-in parser

• Modular applications– Mixins, dependency injection, DCI

(data, context & interaction)

Page 11: Scala en

How?

•Function as input argument•Pattern matching, case classes•Parametric polymorphism

•Traits•Higher-order functions

•Function as output argument•Implicits

• Manipulation of data structures – collections, trees, ADTs, ...

• Internal/External DSLs– OSGi, Apache Camel, scala-query,

specs, built-in parser

• Modular applications– Mixins, dependency injection, DCI

(data, context & interaction)

Page 12: Scala en

Function as value

Manipulation of data structuresCollectionsTreesDSL

Page 13: Scala en

Example - filtering

Javapublic Collection<Ticket> approved(Collection<Ticket> tickets){

Collection<Ticket> result = new ArrayList<Ticket>();for(Ticket ticket : tickets){

if(ticket.getState() == State.APPROVED)result.add(icket);

}return result;

}

Page 14: Scala en

Example - filtering

Javapublic Collection<Ticket> approved(Collection<Ticket> tickets){

Collection<Ticket> result = new ArrayList<Ticket>();for(Ticket ticket : tickets){ filter

if(ticket.getState() == State.APPROVED)result.add(ticket);

}return result;

}

With what?

What to do?

How?

Page 15: Scala en

Yes, it can be done in Javapublic interface ICondition<T> {

public boolean check(T toBeChecked);}

Interface for conditon

... and the use

Filter util method

public static <T> Collection<T> filter(Collection<T> ts, ICondition<T> c){Collection<T> result = new ArrayList<T>();for(T t : ts)

if(c.check(t)) result.add(t);return result;

}

CollestionUtils.filter(verzie, new ICondition<Ticket>() {public boolean check(Ticket toBeChecked){return toBeChecked.getState() == State.APPROVED;}

});

Page 16: Scala en

Example - filtering

Scala

def approved(tickets: List[Ticket]) {tickets filter (_.getState() == State.APPROVED)

}

Page 17: Scala en

WTF ?

What type has the parameter in the function „filter“?

List[+A] {def filter (p : (A) => Boolean) : List[A]

}

Java : (A) => Booleanpublic interface Function1<O, I> {

O apply(I input);}

interface ICondition<I> extends IFunction1<Boolean, I> {}

Page 18: Scala en

Scala List

count (p : (A) => Boolean) : Intexists (p : (A) => Boolean) : Booleanfilter (p : (A) => Boolean) : List[A] find (p : (A) => Boolean) : Option[A] foldLeft [B](z : B)(f : (B, A) => B) : Bforall (p : (A) => Boolean) : Booleanforeach (f : (A) => Unit) : Unitmap [B](f : (A) => B) : List[B] remove (p : (A) => Boolean) : List[A]

Page 19: Scala en

Scala List

count (p : (A) => Boolean) : Intexists (p : (A) => Boolean) : Booleanfilter (p : (A) => Boolean) : List[A] find (p : (A) => Boolean) : Option[A] foldLeft [B](z : B)(f : (B, A) => B) : Bforall (p : (A) => Boolean) : Booleanforeach (f : (A) => Unit) : Unitmap [B](f : (A) => B) : List[B] remove (p : (A) => Boolean) : List[A]

Most of them is inherited from trait Iterable. So every collection, array has them, because they inherit from Iterable.

Similar functions can be written for trees.

Page 20: Scala en

Function can be assigned to variable

var f : (String => Unit) = (x) => println(x)

Function can be passed to another function

tickets filter (t => t.getState() == State.APPROVED)

Return value from function can be a function

def deductKind = tax | insurance | retirement

Function is primitive type, basic building block, with the same importance as an integer or a string.

If functions takes another function as an argument or if it returns a function, it is called a higher-order function.

Page 21: Scala en

ExamplesList(1, 2, 3, 4, 5) map { _ * 2 }> List[Int] = List(2, 4, 6, 8, 10)

case class Employee( var name : String)case class DTOEmployee( var name : String)

def toDto(e : Employee) = new DTOZamestnanec(z.meno)

List(new Employee(“John"), new Employee(“Jack")) map toDto> List[DTOEmployee] = List(DTOEmployee(John),

DTOEmployee(Jack))

Numbers multiplied by two

Employees to DTOs

Page 22: Scala en

Type declaration

In Scala types are written after colon

exists (p : (A) => Boolean) : Boolean

var age : Int = 24 val age = 33

Return type of function exists

Argument p is of type function from A to Boolean

Type of variable age

If type is unambiguous, it doesn’t have to be declared

Page 23: Scala en

Val vs Var• immutable (v Java it would be final)• creates field and getter

val age:Int=22age = 33 //ERROR

• variable• creates field, getter and setter

var age:Int=22age = 33

Page 24: Scala en

List

val list1 = List("Programming", "Scala") val list2 = "People" :: "should" :: "read" :: list1

val list2 = ("People" :: ("should" :: ("read" :: list1))) val list2 = list1.::("read").::("should").::("People")

Operator :: is bound from right

list2

Page 25: Scala en

Mapval stateCapitals = Map( "Alabama" -> "Montgomery", "Alaska" -> "Juneau", "Wyoming" -> "Cheyenne")

val lengths = stateCapitals map { kv => (kv._1, kv._2.length)}

println(lengths)

> Map(Alabama -> 10, Alaska -> 6, Wyoming -> 8)

State -> Capitalis mapped toState -> length of the capital name

Page 26: Scala en

FoldLeft

def foldLeft[B](z: B)(op: (B, A) => B): B = this match { case Nil => z case x :: xs => (xs foldLeft op(z, x))(op)}

Page 27: Scala en

FoldLeftList(1,2,3,4,5).foldLeft(10)(_ * _)(((((10 * 1) * 2) * 3) * 4) * 5)

List(1,2,3,4,5).foldLeft(10)( (x, y) => x +y)(((((10 + 1) + 2) + 3) + 4) + 5)

Shortcut for arguments of anonymous functions. First underscore means the first argument, second the second…

Page 28: Scala en

QuestionsHow would we write function “sum” with the help of foldLeft?

How would we write function “distinct“with the help of foldLeft? (Selects only distinct elements form the list.)

def sumInt(l : List[Int]) : Int = l.foldLeft(0)(_ + _)

def distinct[A](l : List[A]) : List[A] = (l foldLeft List[A]()) {(res, a)=> if (!res.contains(a)) a :: res else res}

Page 29: Scala en

Every value is an objectEvery operator a method

factorial (x - 1)factorial (x.-(1))

map.containsKey(‘a’)map containsKey ‘a’

There are no operators in Scala. Method names can contain some symbols.

Every method can be called on the object without the dot and the brackets.

Page 30: Scala en

There are no operators in Scala. Method names can contain some symbols.

trait Ordered[A] extends java.lang.Comparable[A] {

def compare(that: A): Int

def < (that: A): Boolean = (this compare that) < 0 def > (that: A): Boolean = (this compare that) > 0 def <= (that: A): Boolean = (this compare that) <= 0 def >= (that: A): Boolean = (this compare that) >= 0 def compareTo(that: A): Int = compare(that)}

Page 31: Scala en

“While” doesn’t have to be a keyword... But it is...

def whileAwesome(conditional: => Boolean)(f: => Unit) { if (conditional) { f whileAwesome(conditional)(f) }}

var count = 0whileAwesome(count < 5) { println("still awesome") count += 1}

>still awesome still awesome still awesome still awesome still awesome

Conditional is of type (=> Boolean) , so it is evaluated in the function “whileAwesome”

If conditional was of type Boolean, it would be evaluated before calling the function so the loop would never stop writing "still awesome"

Page 32: Scala en

It has many real life uses

tx { val person = new Person(id=null, name= "Ivanka"); manager.persist(person) }

def tx(f: => Unit) = { manager.getTransaction().begin() try { tx manager.getTransaction().commit() } catch { case e: Exception => manager.getTransaction().rollback() }}

Page 33: Scala en

Functions are objects too

trait Function1[-S, +T] { def apply(x: S): T}

E.g. anonymous function (x: Int ) => x + 1 is translated by the compiler to

new Function1[Int, Int] { def apply(x: Int): Int = x + 1}

Page 34: Scala en

Functions are objects too

Array[T] is a function Int => T, so if such function is needed we can pass an Array[T]

class Array [T] ( length: Int ) extends (Int => T) { def length: Int = ... def apply(i: Int): T = ... def update(i: Int, x: T): Unit = ... def elements: Iterator[T] = ... def exists(p: T => Boolean):Boolean = ...}

While (=>) is a class, it can be inherited from it.So we can specialize the concept of a function.

Instead ofa(i) = a(i) + 2we can writea.update(i, a.apply(i) + 2)

Page 35: Scala en

Currying

Partial function application

Page 36: Scala en

CurryingFunction can return a function

def cat(s1: String)(s2: String) = s1 + s2

def cat(s1: String) = (s2: String) => s1 + s2

cat("foo")("bar") > java.lang.String = foobar

cat("foo") returns a function {(s2 : Int) => “foo” + s2}, to which is passed an argument "bar"

Both notations are correct

Page 37: Scala en

Curryingdef cat(s1: String, s2: String) = s1 + s2> cat: (String,String) java.lang.String

val curryCat = Function.curried(cat _)> curryCat: (String) => (String) => java.lang.String = <function>

cat("foo", "bar") == curryCat("foo")("bar")> res2: Boolean = true

Function.curried() converts functions to their curried form

Page 38: Scala en

Partial function application

val curryCat = Function.curried(cat _)> curryCat: (String) => (String) => java.lang.String = <function>

val partialCurryCat = curryCat("foo")(_)> partialCurryCat: (String) => java.lang.String = <function>

partialCurryCat("bar")> res3: java.lang.String = foobar

Partial application= we didn’t passed all parameters

Page 39: Scala en

Partial function application

val numbers= List(1, 2, 3, 4, 5);

println( numbers map ( 8 +))

def plus(a : Int)(b : Int) : Int = a + bval plusFive = plus(5) _println( numbers map plusFive )

f(B : b) : C

f(A : a)(B : b) : C

It is not needed to pass all parametersUses Currying

Page 40: Scala en

„There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.”

C.A.R. Hoare, author of Quicksort

Page 41: Scala en

Quicksortdef sort(xs: Array[Int]) {def swap(i: Int, j: Int) {

val t = xs(i); xs(i) = xs(j); xs(j) = t}def sort1(l: Int, r: Int) {

val pivot = xs((l + r) / 2)var i = l; var j = rwhile (i <= j) {

while (xs(i) < pivot) i += 1while (xs(j) > pivot) j -= 1if (i <= j) {swap(i, j)i += 1j -= 1}

}if (l < j) sort1(l, j)if (j < r) sort1(i, r)

}sort1(0, xs.length 1)

}

def sort(xs: Array[Int]): Array[Int] =if (xs.length <= 1) xselse {

val pivot = xs(xs.length / 2)Array.concat( sort(xs filter (pivot >)), xs filter (pivot ==), sort(xs filter (pivot <)))

}

Functional

Imperative

Page 42: Scala en

Implicits

Implicit conversions

Page 43: Scala en

Implicits

implicit def intToPimpedInt(i : Int) = new PimpedInt(i)

def main(args: Array[String]) {

3 times println("sdfs")

println(5 minutes)}

class PimpedInt(i : Int){def times(f : => Unit) : Unit = for(x <- 0 until i) fdef seconds = 1000 * idef minutes = 60 * seconds

}

intToPimpedInt(3).times(println("sdfs"))

times(f : => Unit)seconds()minutes()

println(intToPimpedInt(3).minutes())

Only single implicit can be used (they

can not chain)!

Page 44: Scala en

object Complex {val i = new Complex(0, 1)implicit def double2complex(x: Double) : Complex = new Complex(x, 0)

}class Complex(val re: Double, val im: Double) {

def + (that: Complex): Complex = new Complex(this.re + that.re, this.im + that.im)def - (that: Complex): Complex = new Complex(this.re - that.re, this.im - that.im)def * (that: Complex): Complex = new Complex(this.re * that.re - this.im * that.im,

this.re * that.im + this.im * that.re)def / (that: Complex): Complex = {

val denom = that.re * that.re + that.im * that.im new Complex((this.re * that.re + this.im * that.im) / denom, (this.im * that.re - this.re * that.im) / denom)

}override def toString = re+(if (im < 0) "-"+(-im) else "+"+im)+"*i"

}

By importing Complex one can use complex numbers like they were built in language feature.

import pads.Complex._object ComplexTest {

def main(args: Array[String]) {val x : Complex = 4 + 3 * ival y : Complex = x * i println(y)

}}

Page 45: Scala en

Structural typing

“Type safe duck typing”

Page 46: Scala en

Structural typingclass Employee {

var meno : String = null}

class Firm {var title : String = nulldef name = "Firm is called " + title

}

Attribute name

Method name

Employee and Firm does not have a common supertype

Page 47: Scala en

Structural typingdef getName(x : {val name : String}) : String = x.namedef setName(x : {var name : String}) : Unit = x.name = "new name"

val employee = new Employee()employee.name = “Kate"val firm = new Firm()firm.name = "PosAm"

println (getName(employee))println (getName(firm))

println (setName(employee))println (setName(firm)) //ERROR

type mismatch; found : firm.type (with underlying type pads.Firm) required: AnyRef{def name: String; def name_=(x$1: String): Unit}

Page 48: Scala en

DSL - domain specific language

ImplicitsHigher order functionsOptional dots, semi-colons, parenthesesOperators like methodsCurrying

Page 49: Scala en

DSL

External DSL+ own language, freedom- need to write a parser- extensible from inside

Internal DSL+ extensible from outside,

it’s just a library- syntax of a host language

Parser library in Scala simplifies writing external DSLs

Implicits, higher-order functions, optional dots and brackets, operator methods and currying simplifies writing of internal DSLs

Page 50: Scala en

External DSL written with the help of library scala.util.parsing.combinator._

/** @return Parser[Money] */ def percentage = toBe ~> doubleNumber <~ "percent" <~ "of" <~ "gross" ^^ { percentage => grossAmount * (percentage / 100.) }

def amount = toBe ~> doubleNumber <~ "in" <~ "gross" <~ "currency" ^^ { Money(_) }

def toBe = "is" | "are"

def doubleNumber = floatingPointNumber ^^ { _.toDouble }

|, ~> , <~, ^^ are just functionsLibrary pasing.combinator is internal DSL

Page 51: Scala en

^^

/** A parser combinator for function application * *<p>`p ^^ f' succeeds if `p' succeeds; it returns `f' applied to the result of `p'.</p> * * @param f a function that will be applied to this parser's result (see `map' in `ParseResult'). * @return a parser that has the same behaviour as the current parser, but whose result is * transformed by `f'. */ def ^^ [U](f: T => U): Parser[U] = map(f).named(toString+"^^")

Page 52: Scala en

Trait

Mixins Dependency injection Data, context & interaction

Page 53: Scala en

Types

Class Object TraitObject has only a single instance. One can obtain this instance by writing object’s name. It can be extended by the Traits.

Like an interface/abstract class.Can have an implementation.Can not have a constructor.

Class can inherit from one class but it can be extended by several Traits.

Page 54: Scala en

Dependency injectionclass UserRepository { def authenticate(user: User): User = { println("authenticating user: " + user) user } def create(user: User) = println("creating user: " + user) def delete(user: User) = println("deleting user: " + user) }

class UserService { def authenticate(username: String, password: String): User = userRepository.authenticate(username, password) def create(username: String, password: String) = userRepository.create(new User(username, password)) def delete(user: User) = All is statically typed. userRepository.delete(user) }

UserRepository can have more implementations.

UserService is dependent onUserRepository. It can have more implementations as well.

Page 55: Scala en

Cake Pattern

trait UserRepositoryComponent { val userRepository: UserRepository class UserRepository { ... } }

trait UserServiceComponent { this: UserRepositoryComponent =>

val userService: UserService

class UserService { ... }}

Classes are wrapped in components (traits), where its dependencies are declared.

Page 56: Scala en

Cake Pattern

object ComponentRegistry extends UserServiceComponent with UserRepositoryComponent { val userRepository = new UserRepository val userService = new UserService}

In the result object we set implementations of all necessary components. Every component uses right implementation on which it is dependent.

Page 57: Scala en

Case class

ADTPattern matching

Page 58: Scala en

Pattern matching

val randomInt = new Random().nextInt(10)

randomInt match { case 7 => println( "lucky seven!" ) case otherNumber => println(„not seven " + otherNumber)}

Matching by values

Java swicht-case analogy

Page 59: Scala en

Pattern matching

val sundries = List(23, "Hello", 8.5, 'q') for (sundry <- sundries) { sundry match { case i: Int => println("got an Integer: " + i) case s: String => println("got a String: " + s) case f: Double => println("got a Double: " + f) case other => println("got something else: " + other) } }

Matching by type

Page 60: Scala en

Pattern matching

val willWork = List(1, 3, 23, 90)val willNotWork = List(4, 18, 52)val empty = List()

for (l <- List(willWork, willNotWork, empty)) { l match { case List(_, 3, _, _) => println("4 elements, with the 2nd being '3'.") case List(_*) => println("Any other list with 0 or more elements.") }}

Matching of sequences

Page 61: Scala en

Pattern matching

val tupA = ("Good", "Morning!") val tupB = ("Guten", "Tag!") for (tup <- List(tupA, tupB)) { tup match { case (thingOne, thingTwo) if thingOne == "Good"

=> println("A two-tuple starting with 'Good'.") case (thingOne, thingTwo)

=> println("Two things: " + thingOne + " and " + thingTwo) } }

Matching of tuples

Page 62: Scala en

Pattern matching

case class Person(name: String, age: Int)val alice = new Person("Alice", 25)val bob = new Person("Bob", 32)val charlie = new Person("Charlie", 32)

for (person <- List(alice, bob, charlie)) { person match { case Person("Alice", 25) => println("Hi Alice!") case Person("Bob", 32) => println("Hi Bob!") case Person(name, age) => println(age + " years old person named " + name ) }}

Matching of case classes

Page 63: Scala en

Recap

Scala is a multi-paradigm languageObject-oriented – objects, classes, traits,

inheritance, polymorphism, encapsulationFunctional – function is a value, pattern matching,

parametric polymorphism (generics), case classes(Dynamic-types) – implicits, traits, structural

typing, type inference These features give programmers a feel of

language with dynamic types. Although all types are checked in compilation time.

Page 64: Scala en

And I haven’t mention

• Implicit function parameters• Lazy values• XML built in syntax• Actor

...

And it works with Hibernate, Spring, Guice, Maven, Wicket...

Page 65: Scala en

Want to know more?

programming-scala.labs.oreilly.com

www.scala-lang.org

Page 66: Scala en

Finally end