KEMBAR78
Scala: Object-Oriented Meets Functional, by Iulian Dragos | PDF
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 2008 
3
Scala drives its social graph service: 
380-400 M transactions/day 
Migrated core messaging service 
from Ruby to sustain 1000x growth 
Approved for general production 
use 
Location-based social network. All 
written in Scala (>5M users). 
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 function 
8
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
The bottom line 
•Every value is an object 
•Everything is an expression (evaluates to 
a value) 
•Every operation is a method call 
•What about primitives? 
12
type can be inferred 
val x: Int = 10 
val y = x + 10 
same as x.+(10) 
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 + c1 
res0: 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 
no return statement 
scala> val t = { 
| x = x + 10 
| x - 1 
| } 
t: Int = 9 
return type inferred to Int 
blocks evaluate to last 
expression 
18
What about println? 
scala> val x = println("hello, world") 
hello, world 
x: 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
explicit abstract class parameters/fields 
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 
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
type parameter can extend Java classes 
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 
} 
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
A trait for undoable cells 
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) 
} 
29
A trait for logging cells 
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) 
} 
} 
30
Mix-in composition 
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] 
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 
Undo Logging
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 { 
requires module Customers 
def getCustomers: Unit = () 
//... 
} 
} 
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
This gives dependency 
injection in the language! 
object TestApp extends Accounting 
with Customers { 
val logger = // println based 
val customers = new MockCustomerService 
} 
The test environment uses a mock CustomerService. 
38
Summary 
•Basic O-O features 
•classes and traits 
•type inference 
•mix-in composition 
•Advanced type system 
•modules and dependencies 
•dynamic binding of super 
39
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 + 1 
succ: (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: Maps 
scala> 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> capitals 
res9: 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 
may have any number of generators 
p is in scope for other generators 
for (p <- persons; pr <- p.projects; 
if pr.overdue) yield p.name 
guard construct a new collection of the same 
type, element by element 
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 matching 
abstract 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 matching 
def 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
try { 
//... 
} catch { 
case EvalError(line, msg) => //.. 
case e: IndexOutOfBoundsException => //.. 
} 
61
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 
} 
Also a great way to adapt existing libraries 
66
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 
67
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 
asynchronous message send 
method call 
receive { 
case Ping(a1) => a1 ! msg 
case Pong(_) => .. 
} 
Normal pattern match translated 
to PartialFunction 
69
What else? 
70
Lots 
•Parallel collections 
library! 
•Staging 
the in •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

Scala: Object-Oriented Meets Functional, by Iulian Dragos

  • 1.
    Scala: Object-Oriented meetsFunctional An overview of the Scala programming language Iulian Dragos 1
  • 2.
    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
  • 3.
    History •“Make Javabetter” •1997 - Pizza and GJ (Odersky, Wadler) •2000 - Java 5 (generics) •“Make a better Java” •first release 2004 •adoption begins 2007 •first Scala conference 2008 3
  • 4.
    Scala drives itssocial graph service: 380-400 M transactions/day Migrated core messaging service from Ruby to sustain 1000x growth Approved for general production use Location-based social network. All written in Scala (>5M users). 5
  • 5.
    Philosophy • “Growablelanguage” (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
  • 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
  • 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 function 8
  • 8.
    Overview •Scala asan Object-Oriented Language •Scala as a Functional Programming Language •Scala as a host language for DSLs 9
  • 9.
  • 10.
    Running Scala •Compiledto Java bytecode •Read-Eval-Print-Loop (REPL) •fast turnaround •easy experimentation/testing 11
  • 11.
    The bottom line •Every value is an object •Everything is an expression (evaluates to a value) •Every operation is a method call •What about primitives? 12
  • 12.
    type can beinferred val x: Int = 10 val y = x + 10 same as x.+(10) 13
  • 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
  • 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
  • 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 + c1 res0: test.Complex = 3 + 4i 16
  • 16.
    Everything is an expression •No statements •Reduces the need for return and side-effects 17
  • 17.
    def max(x: Int,y: Int) = if (x > y) x else y no return statement scala> val t = { | x = x + 10 | x - 1 | } t: Int = 9 return type inferred to Int blocks evaluate to last expression 18
  • 18.
    What about println? scala> val x = println("hello, world") hello, world x: Unit = () The Unit type is like void in Java: no interesting value 19
  • 19.
  • 20.
    Classes •Similar toJava classes •have fields, methods, parameters and types •every member can be overridden •except classes (no virtual classes) •any member can be abstract 21
  • 21.
    explicit abstract classparameters/fields 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 super ctor call When compiled, this class will look and behave exactly like the obvious translation to a Java class. No glue code necessary.
  • 22.
    Traits •Like Javainterfaces, 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
  • 23.
    type parameter canextend Java classes 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 } classes mixing in Ordered will get all these methods ‘for free’ class Complex extends Ordered[Complex] { def compare(that: Complex): Int = ... } 24
  • 24.
    if (c1 >c2) c1 else c2 val xs: List[Complex] xs.sorted 25
  • 25.
  • 26.
    Mix-in example: Cells •model mutable cells that contain a single value of some arbitrary type. •Additionally, define logging and undoable variants. 27
  • 27.
    A class forgeneric 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
  • 28.
    A trait forundoable cells 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) } 29
  • 29.
    A trait forlogging cells 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) } } 30
  • 30.
    Mix-in composition newCell(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] cell with logging cell with logging and undoing cell with undoing and logging 31
  • 31.
    Mix-in composition •traitscan be stacked •the call to super is dynamically bound •super calls the ‘preceding’ implementation in the instantiated object 32
  • 32.
    Late binding forsuper 33 Cell myCell Undo Logging
  • 33.
    Modules •Scala usesobjects and traits for module composition •Composition through mixins •Modules may require another module 34
  • 34.
    Customers and DB •Module Accounting •requires a logger, a customer service •Module Customers •requires a logger, provides the customer service 35
  • 35.
    trait Accounting {this: Customers => val logger: Logger customers.getCustomers // .. } trait Customers { val logger: Logger val customers: CustomerService class CustomerService { requires module Customers def getCustomers: Unit = () //... } } 36
  • 36.
    object App extendsAccounting with Customers { val logger = // logback val customers = new CustomerService } The application uses (some) concrete implementations of Accounting and CustomerService. 37
  • 37.
    This gives dependency injection in the language! object TestApp extends Accounting with Customers { val logger = // println based val customers = new MockCustomerService } The test environment uses a mock CustomerService. 38
  • 38.
    Summary •Basic O-Ofeatures •classes and traits •type inference •mix-in composition •Advanced type system •modules and dependencies •dynamic binding of super 39
  • 39.
  • 40.
    What is FP? •Use of functions (in the mathematical sense) •referential transparency (no side-effects) •Immutable objects •Functions are values 41
  • 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
  • 42.
    Function literals scala>val succ = (x: Int) => x + 1 succ: (Int) => Int = <function1> scala> succ(1) res3: Int = 2 43
  • 43.
    Equivalent forms •x=> x + 1 (infer type) •1 + (partial application) •_ + 1 (placeholder notation) •compare _ (eta expansion) 44
  • 44.
    Higher-Order Functions •functionsthat take or return functions •almost eliminate the need for loops over collections 45
  • 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
  • 46.
    Everything is anobject •Closures are objects as well •(compiler generated) instances of trait Function1[A, B] trait Function1[R, A] { def apply(x: A): R } 47
  • 47.
    (More) sugar •..butwhy 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
  • 48.
    Library •Yes! Lotsof collections are functions •Sequences are Int => T •Sets are T => Boolean •Maps are K => V 49
  • 49.
  • 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
  • 51.
    Example: Maps scala>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> capitals res9: 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
  • 52.
    For-comprehensions •More generalthan for-loops •Used to iterate, filter and generate new collections 53
  • 53.
    For-comprehensions may haveany number of generators p is in scope for other generators for (p <- persons; pr <- p.projects; if pr.overdue) yield p.name guard construct a new collection of the same type, element by element res10: List[String] = List(“John”, “Harry”) 54
  • 54.
    For-comprehensions •Desugared tocalls 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
  • 55.
  • 56.
    Pattern matching •Away to deconstruct structured data •A powerful switch statement (expression, really) 57
  • 57.
    Pattern matching abstractclass 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
  • 58.
    Pattern matching defopt(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
  • 59.
    Patterns everywhere •Greatway to process XML, JSON, etc. •exception handlers are also patterns! •..and also declarations 60
  • 60.
    try { //... } catch { case EvalError(line, msg) => //.. case e: IndexOutOfBoundsException => //.. } 61
  • 61.
  • 62.
    Implicit conversions •Wecan “grow” the language with Complex numbers •c + 1 works, but what about 1 + c? 63
  • 63.
    Implicit conversions •Allowuser-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
  • 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
  • 65.
    implicit class RichInt(n:Int) { def + (other: Complex) = new Complex(n) + other } Also a great way to adapt existing libraries 66
  • 66.
    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 67
  • 67.
    Actor-based concurrency •Threadsand 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
  • 68.
    Actors in Scala actor ! msg asynchronous message send method call receive { case Ping(a1) => a1 ! msg case Pong(_) => .. } Normal pattern match translated to PartialFunction 69
  • 69.
  • 70.
    Lots •Parallel collections library! •Staging the in •Call-by-name parameters •Specialization 71
  • 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
  • 72.