72
Scala: Object-Oriented meets Functional An overview of the Scala programming language Iulian Dragos 1

Scala: Object-Oriented Meets Functional, by Iulian Dragos

Embed Size (px)

DESCRIPTION

A presentation from Iulian Dragos of Typesafe that gives an overview of the Scala programming language. The presentation was given at a Functional Angle conference in Timisoara, Romania sponsored by 3Pillar. Iulian Dragos has been working on Scala since 2004. He currently works for Typesafe, a start-up that was co-founded by Scala’s creator, Martin Odersky.

Citation preview

Page 1: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Scala: Object-Oriented meets Functional

An overview of the Scala programming language

Iulian Dragos

1

Page 2: Scala: Object-Oriented Meets Functional, by Iulian Dragos

What is Scala?

•A programming language running on the JVM (also a JS backend)

•Statically typed, combines object-orientation and functional programming

•Concise

•Fully interoperable with Java

•As fast as Java

2

Page 3: Scala: Object-Oriented Meets Functional, by Iulian Dragos

History

•“Make Java better”

•1997 - Pizza and GJ (Odersky, Wadler)

•2000 - Java 5 (generics)

•“Make a better Java”

•first release 2004

•adoption begins 2007

•first Scala conference 20083

Page 4: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Scala drives its social graph service: 380-400 M transactions/day

Migrated core messaging service from Ruby to sustain 1000x growth

Location-based social network. All written in Scala (>5M users).

Approved for general production use

5

Page 5: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Philosophy

• “Growable language” (Guy Steele)

• embed DSLs/add new types

• Scalable language

• same concepts in small and large applications

• Deep rather than broad

• focus on abstraction and composition

6

Page 6: Scala: Object-Oriented Meets Functional, by Iulian Dragos

public class Person { public final String name; public final int age; Person(String name, int age) { this.name = name; this.age = age; }}

class Person(val name: String, val age: Int)

Java

Scala

7

Page 7: Scala: Object-Oriented Meets Functional, by Iulian Dragos

import java.util.ArrayList;...Person[] people;Person[] minors;Person[] adults;{ ArrayList<Person> minorsList = new ArrayList<Person>(); ArrayList<Person> adultsList = new ArrayList<Person>(); for (int i = 0; i < people.length; i++) (people[i].age < 18 ? minorsList : adultsList) .add(people[i]); minors = minorsList.toArray(people); adults = adultsList.toArray(people);}

val people: Array[Person]val (minors, adults) = people partition (_.age < 18)

A tuple in a pattern match

Infix method call

Anonymous function8

Page 8: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Overview

•Scala as an Object-Oriented Language

•Scala as a Functional Programming Language

•Scala as a host language for DSLs

9

Page 9: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Scala Basics

10

Page 10: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Running Scala

•Compiled to Java bytecode

•Read-Eval-Print-Loop (REPL)

•fast turnaround

•easy experimentation/testing

11

Page 11: Scala: Object-Oriented Meets Functional, by Iulian Dragos

•Every value is an object

•Everything is an expression (evaluates to a value)

•Every operation is a method call

•What about primitives?

The bottom line

12

Page 12: Scala: Object-Oriented Meets Functional, by Iulian Dragos

val x: Int = 10val y = x + 10

same as x.+(10)

type can be inferred

13

Page 13: Scala: Object-Oriented Meets Functional, by Iulian Dragos

final class Int { def +(y: Int): Int = <native> def -(y: Int): Int = <native> def *(y: Int): Int = <native> def /(y: Int): Int = <native> ...}

The compiler treats all primitives as if they were instances of such classes (but uses primitive values for performance)

14

Page 14: Scala: Object-Oriented Meets Functional, by Iulian Dragos

class Complex(val re: Int, val im: Int) { def +(that: Complex) = new Complex(this.re + that.re, this.im + that.im) // .. override def toString = "%d + %di".format(re, im)}

15

Page 15: Scala: Object-Oriented Meets Functional, by Iulian Dragos

scala> val c = new Complex(1, 2)c: test.Complex = 1 + 2i

scala> val c1 = new Complex(2, 2)c1: test.Complex = 2 + 2i

scala> c + c1res0: test.Complex = 3 + 4i

16

Page 16: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Everything is an expression

•No statements

•Reduces the need for return and side-effects

17

Page 17: Scala: Object-Oriented Meets Functional, by Iulian Dragos

def max(x: Int, y: Int) = if (x > y) x else y

scala> val t = { | x = x + 10 | x - 1 | }t: Int = 9

no return statement

return type inferred to Int

blocks evaluate to last expression

18

Page 18: Scala: Object-Oriented Meets Functional, by Iulian Dragos

What about println?

scala> val x = println("hello, world")hello, worldx: Unit = ()

The Unit type is like void in Java: no interesting value

19

Page 19: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Classes and Traits

20

Page 20: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Classes

•Similar to Java classes

•have fields, methods, parameters and types

•every member can be overridden

•except classes (no virtual classes)

•any member can be abstract

21

Page 21: Scala: Object-Oriented Meets Functional, by Iulian Dragos

abstract class Node[T](val v: T, next: Node[T]) extends List(v, next) { val cache: Int def first: T def children = List(next) override def toString = "Node " + v}

22

explicit abstract class parameters/fields

super ctor call

When compiled, this class will look and behave exactly like the obvious translation to a Java class. No glue code necessary.

Page 22: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Traits

•Like Java interfaces, but in addition

•allow concrete methods, fields, types

•Like Scala classes, but without constructor parameters

•Allow (a form of) multiple inheritance

•mix-in composition

23

Page 23: Scala: Object-Oriented Meets Functional, by Iulian Dragos

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}

type parameter can extend Java classes

classes mixing in Ordered will get all these methods ‘for free’

class Complex extends Ordered[Complex] { def compare(that: Complex): Int = ...}

24

Page 24: Scala: Object-Oriented Meets Functional, by Iulian Dragos

if (c1 > c2) c1 else c2

val xs: List[Complex]xs.sorted

25

Page 25: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Mix-in composition

26

Page 26: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Mix-in example: Cells

•model mutable cells that contain a single value of some arbitrary type.

•Additionally, define logging and undoable variants.

27

Page 27: Scala: Object-Oriented Meets Functional, by Iulian Dragos

A class for generic cells

class Cell[T](val init: T) { private var v = init

def get(): T = v def set(v1: T): Unit = { v = v1 }

override def toString: String = "Cell("+ v +")"}

make init available as a field

mutable field

28

Page 28: Scala: Object-Oriented Meets Functional, by Iulian Dragos

trait UndoableCell[T] extends Cell[T] { import mutable.ArrayStack private var hist = new ArrayStack[T]()

override def set(v1: T): Unit = { hist.push(super.get()) super.set(v1) }

def undo(): Unit = super.set(hist pop)}

A trait for undoable cells

29

Page 29: Scala: Object-Oriented Meets Functional, by Iulian Dragos

trait LoggingCell[T] extends Cell[T] { override def get(): T = { println("getting "+ this) super.get() }

override def set(v1: T): Unit = { println("setting "+ this +" to "+ v1) super.set(v1) }}

A trait for logging cells

30

Page 30: Scala: Object-Oriented Meets Functional, by Iulian Dragos

new Cell(0)

new Cell(0) with LoggingCell[Int]

new Cell(0) with LoggingCell[Int] with UndoableCell[Int]

new Cell(0) with UndoableCell[Int] with LoggingCell[Int]

Mix-in composition

cell with logging

cell with logging and undoing

cell with undoing and logging

31

Page 31: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Mix-in composition

•traits can be stacked

•the call to super is dynamically bound

•super calls the ‘preceding’ implementation in the instantiated object

32

Page 32: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Late binding for super

33

Cell

myCell

LoggingUndo

Page 33: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Modules

•Scala uses objects and traits for module composition

•Composition through mixins

•Modules may require another module

34

Page 34: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Customers and DB

•Module Accounting

•requires a logger, a customer service

•Module Customers

•requires a logger, provides the customer service

35

Page 35: Scala: Object-Oriented Meets Functional, by Iulian Dragos

trait Accounting { this: Customers => val logger: Logger customers.getCustomers // ..}

trait Customers { val logger: Logger val customers: CustomerService class CustomerService { def getCustomers: Unit = () //... }}

requires module Customers

36

Page 36: Scala: Object-Oriented Meets Functional, by Iulian Dragos

object App extends Accounting with Customers { val logger = // logback val customers = new CustomerService}

The application uses (some) concrete implementations of Accounting and CustomerService.

37

Page 37: Scala: Object-Oriented Meets Functional, by Iulian Dragos

object TestApp extends Accounting with Customers { val logger = // println based val customers = new MockCustomerService}

The test environment uses a mock CustomerService.

This gives dependency injection in the language!

38

Page 38: Scala: Object-Oriented Meets Functional, by Iulian Dragos

39

Summary•Basic O-O features

•classes and traits

•type inference

•mix-in composition

•Advanced type system

•modules and dependencies

•dynamic binding of super

Page 39: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Functional Programming

40

Page 40: Scala: Object-Oriented Meets Functional, by Iulian Dragos

What is FP?

•Use of functions (in the mathematical sense)

•referential transparency (no side-effects)

•Immutable objects

•Functions are values

41

Page 41: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Scala as FPL

•function literals and closures

•use val instead of var

•immutable collections in the standard library

•opt-in lazy evaluation

•curry-ing (definition site)

42

Page 42: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Function literals

scala> val succ = (x: Int) => x + 1succ: (Int) => Int = <function1>

scala> succ(1)res3: Int = 2

43

Page 43: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Equivalent forms

•x => x + 1 (infer type)

•1 + (partial application)

•_ + 1 (placeholder notation)

•compare _ (eta expansion)

44

Page 44: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Higher-Order Functions

•functions that take or return functions

•almost eliminate the need for loops over collections

45

Page 45: Scala: Object-Oriented Meets Functional, by Iulian Dragos

val xs = List(1, 2, 3, 4, 5)xs.foreach(println)

scala> xs.forall(_ < 10)res5: Boolean = true

scala> xs.map(_ * 2)res6: List[Int] = List(2, 4, 6, 8, 10)

def findBelow(limit: Int) = persons.filter(_.age < limit)

lexical scoping: functions may refer and even modify anything in scope

46

Page 46: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Everything is an object

•Closures are objects as well

•(compiler generated) instances of trait Function1[A, B]

trait Function1[R, A] { def apply(x: A): R}

47

Page 47: Scala: Object-Oriented Meets Functional, by Iulian Dragos

(More) sugar

•..but why can I call succ(10)?

•f(args) is desugared to f.apply(args)

•you can define your own ‘apply’ methods

•..can I subclass FunctionN?

48

Page 48: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Library

•Yes! Lots of collections are functions

•Sequences are Int => T

•Sets are T => Boolean

•Maps are K => V

49

Page 49: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Standard Library

50

Page 50: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Collections

•Generic (List[T], Map[K, V])

•Mutable and immutable implementations (default is immutable)

•Uniform (same method protocol for all collections)

•Uniform Return Principle

•No compiler magic!

51

Page 51: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Example: Mapsscala> val capitals = Map("France" -> "Paris", "Switzerland" -> "Bern", "Sweden" -> "Stockholm")capitals: immutable.Map[String,String] = Map(France -> Paris, Switzerland -> Bern, Sweden -> Stockholm)

scala> capitals("France")res7: java.lang.String = Paris

scala> capitals + ("Romania" -> "Bucharest")res8: immutable.Map[String,String] = Map(France -> Paris, Switzerland -> Bern, Sweden -> Stockholm, Romania -> Bucharest)

scala> capitalsres9: immutable.Map[String,String] = Map(France -> Paris, Switzerland -> Bern, Sweden -> Stockholm)

scala> capitals.filter(_._2 == "Paris")res10: immutable.Map[String,String] = Map(France -> Paris)

52

Page 52: Scala: Object-Oriented Meets Functional, by Iulian Dragos

For-comprehensions

•More general than for-loops

•Used to iterate, filter and generate new collections

53

Page 53: Scala: Object-Oriented Meets Functional, by Iulian Dragos

For-comprehensions

for (p <- persons; pr <- p.projects; if pr.overdue) yield p.name

may have any number of generators

guard construct a new collection of the same type, element by element

p is in scope for other generators

res10: List[String] = List(“John”, “Harry”)54

Page 54: Scala: Object-Oriented Meets Functional, by Iulian Dragos

For-comprehensions

•Desugared to calls to filter, map, flatMap

•..any class implementing those methods

•Could be used to query a database

•implement filter, map, flatmap to generate and forward SQL

•Slick, ScalaQuery, Squeryl

55

Page 55: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Pattern matching

56

Page 56: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Pattern matching

•A way to deconstruct structured data

•A powerful switch statement (expression, really)

57

Page 57: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Pattern matchingabstract class Expr

case class Literal(n: Int) extends Expr

case class Add(left: Expr, right: Expr) extends Expr

case class Mul(left: Expr, right: Expr) extends Expr

the case modifier enables these classes to participate in pattern matching

58

Page 58: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Pattern matchingdef opt(e: Expr) = e match { case Add(l, Literal(0)) => l

case Mul(l, Literal(1)) => l

case _ => e}

patterns can be nested

literals match only their value

default case

59

Page 59: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Patterns everywhere

•Great way to process XML, JSON, etc.

•exception handlers are also patterns!

•..and also declarations

60

Page 60: Scala: Object-Oriented Meets Functional, by Iulian Dragos

61

try { //... } catch { case EvalError(line, msg) => //.. case e: IndexOutOfBoundsException => //.. }

Page 61: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Embedding DSLs

62

Page 62: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Implicit conversions

•We can “grow” the language with Complex numbers

•c + 1 works, but what about 1 + c?

63

Page 63: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Implicit conversions

•Allow user-defined conversions

•When the type does not have a member

•Find a method marked implicit that takes the original type to one that has it

•Call the method implicitly

•It’s an error to have more than one applicable conversions

64

Page 64: Scala: Object-Oriented Meets Functional, by Iulian Dragos

implicit def intIsComplex(n: Int) = new RichInt(n)

class RichInt(n: Int) { def + (other: Complex) = new Complex(n) + other}

1 + c intIsComplex(1).+(c)65

Page 65: Scala: Object-Oriented Meets Functional, by Iulian Dragos

implicit class RichInt(n: Int) { def + (other: Complex) = new Complex(n) + other}

66

Also a great way to adapt existing libraries

Page 66: Scala: Object-Oriented Meets Functional, by Iulian Dragos

67

implicit class RichArray[T](as: Array[T]) { def foreach(f: T => Unit) = ??? def map[U](f: T => U) = ??? def filter(f: T => Boolean) = ??? // ... }

Scala arrays are Java arrays, but can still have the same API

Page 67: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Actor-based concurrency

•Threads and locks are error-prone

•(in fact, mutable shared data)

•Alternative: Message-passing with actors

•(no sharing)

•Implemented entirely in the library

•(3 other implementations out there)

68

Page 68: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Actors in Scala

actor ! msg

receive { case Ping(a1) => a1 ! msg case Pong(_) => ..}

asynchronous message send

Normal pattern match translated to PartialFunction

method call

69

Page 69: Scala: Object-Oriented Meets Functional, by Iulian Dragos

What else?

70

Page 70: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Lots

•Parallel collections

•Staging in the

librar

y!

•Call-by-name parameters

•Specialization

71

Page 71: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Where to start•Pick one of the books

•Scala for the Impatient (Addison-Wesley)

•Atomic Scala (Bruce Eckel)

•Scala for Java refugees (blog)

72

Page 72: Scala: Object-Oriented Meets Functional, by Iulian Dragos

Thank you!

73