Upload
3pillar-global
View
360
Download
0
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
Scala: Object-Oriented meets Functional
An overview of the Scala programming language
Iulian Dragos
1
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
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
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
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
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
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
Overview
•Scala as an Object-Oriented Language
•Scala as a Functional Programming Language
•Scala as a host language for DSLs
9
Scala Basics
10
Running Scala
•Compiled to Java bytecode
•Read-Eval-Print-Loop (REPL)
•fast turnaround
•easy experimentation/testing
11
•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
val x: Int = 10val y = x + 10
same as x.+(10)
type can be inferred
13
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
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
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
Everything is an expression
•No statements
•Reduces the need for return and side-effects
17
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
What about println?
scala> val x = println("hello, world")hello, worldx: Unit = ()
The Unit type is like void in Java: no interesting value
19
Classes and Traits
20
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
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.
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
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
if (c1 > c2) c1 else c2
val xs: List[Complex]xs.sorted
25
Mix-in composition
26
Mix-in example: Cells
•model mutable cells that contain a single value of some arbitrary type.
•Additionally, define logging and undoable variants.
27
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
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
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
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
Mix-in composition
•traits can be stacked
•the call to super is dynamically bound
•super calls the ‘preceding’ implementation in the instantiated object
32
Late binding for super
33
Cell
myCell
LoggingUndo
Modules
•Scala uses objects and traits for module composition
•Composition through mixins
•Modules may require another module
34
Customers and DB
•Module Accounting
•requires a logger, a customer service
•Module Customers
•requires a logger, provides the customer service
35
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
object App extends Accounting with Customers { val logger = // logback val customers = new CustomerService}
The application uses (some) concrete implementations of Accounting and CustomerService.
37
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
39
Summary•Basic O-O features
•classes and traits
•type inference
•mix-in composition
•Advanced type system
•modules and dependencies
•dynamic binding of super
Functional Programming
40
What is FP?
•Use of functions (in the mathematical sense)
•referential transparency (no side-effects)
•Immutable objects
•Functions are values
41
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
Function literals
scala> val succ = (x: Int) => x + 1succ: (Int) => Int = <function1>
scala> succ(1)res3: Int = 2
43
Equivalent forms
•x => x + 1 (infer type)
•1 + (partial application)
•_ + 1 (placeholder notation)
•compare _ (eta expansion)
44
Higher-Order Functions
•functions that take or return functions
•almost eliminate the need for loops over collections
45
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
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
(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
Library
•Yes! Lots of collections are functions
•Sequences are Int => T
•Sets are T => Boolean
•Maps are K => V
49
Standard Library
50
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
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
For-comprehensions
•More general than for-loops
•Used to iterate, filter and generate new collections
53
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
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
Pattern matching
56
Pattern matching
•A way to deconstruct structured data
•A powerful switch statement (expression, really)
57
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
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
Patterns everywhere
•Great way to process XML, JSON, etc.
•exception handlers are also patterns!
•..and also declarations
60
61
try { //... } catch { case EvalError(line, msg) => //.. case e: IndexOutOfBoundsException => //.. }
Embedding DSLs
62
Implicit conversions
•We can “grow” the language with Complex numbers
•c + 1 works, but what about 1 + c?
63
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
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
implicit class RichInt(n: Int) { def + (other: Complex) = new Complex(n) + other}
66
Also a great way to adapt existing libraries
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
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
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
What else?
70
Lots
•Parallel collections
•Staging in the
librar
y!
•Call-by-name parameters
•Specialization
71
Where to start•Pick one of the books
•Scala for the Impatient (Addison-Wesley)
•Atomic Scala (Bruce Eckel)
•Scala for Java refugees (blog)
72
Thank you!
73