SlideShare une entreprise Scribd logo
1  sur  66
Scala With Style
Martin Odersky
This Talk
I’ll argue that we are at a transition period between two
programming paradigms:
Imperative/OOP  Functional.
In the end, we will see a fusion of these.
In light of this development, many questions of
programming techniques and style have to be revisited.
2
How OOP got started
First popular OO language:
Simula 67
Second popular OO language:
Smalltalk
3
Why Did OOP become popular?
Encapsulation?
Code Re-use?
Dynamic Binding
Dependency inversion?
Liskov substition
principle?
Open-closed principle?
It was because of the things you could do with OOP!
4
No
Don’t think so
Not directly
Came much later
You gotta be kidding!
How OOP got started
Traditional approach: Linked List
Two cases: Empty, NonEmpty
Unbounded number of operations:
– map
– reverse
– print
– get elem
– insert
– ...
5
How OOP got started
New challenge: Simulation
Fixed number of operations:
nextStep
toString
aggregate
Unbounded number of implementations:
Car, Road, Molecule, Cell, Person, Building, City, ...
6
How OOP got started
New challenge: GUI widgets
Fixed number of operations:
redraw
boundingRectangle
move
Unbounded number of implementations:
Window, Menu, Letter, Shape, Curve, Image, Video, ...
7
What Simulation and GUIs have in common
Both need a way to execute a fixed API with an unknown
implementation.
It’s possible to do this in a procedural language such as C.
But it’s too cumbersome, so people wanted object-oriented
languages instead.
8
What does this have to do with FP?
Just like OOP did then, FP has lots of methodological
advantages:
– Fewer errors
– Better modularity
– Higher-level abstractions
– Shorter code
– Increased developer productivity
But these alone are not enough for mainstream adoption (after
all FP has been around for 50 years)
Need a catalyzer, something that sparks initial adoption until the
other advantages become clear to everyone.
9
FP on the Rise
• In Computer Science:
Compare #attendees of OOP conferences: OOPSLA, ECOOP
with FP conference: ICFP
12 years ago : ECOOP ~ 3 x ICFP
OOPSLA ~ 10 x ICFP
2012 : ICFP ~ 2 x ECOOP
OOPSLA stopped existing as
independent conf.
• Developer interest: over 100’000 signed up for our
#progfun course Functional Programming Principles in
Scala.
10
A Catalyzer
• Two forces driving software complexity:
• Multicore (= parallel programming)
• Cloud computing (= distributed programming)
• Current languages and frameworks have trouble keeping
up (locks/threads don’t scale)
• Need better tools with the right level of abstraction
11
Triple Challenge
Parallel – how to make use of multicore, GPUs,
clusters?
Async – how to deal with asynchronous events
Distributed – how to deal with delays and failures?
Mutable state is a liability for each one of these!
– Cache coherence
– Races
– Versioning
12
The Essence of Functional Programming
13
Concentrate on transformations
of immutable values
instead of stepwise modifications
of mutable state.
14
What about Objects?
So, should we forget OO and all program in
functional programming languages?
No! What the industry learned about OO
decomposition in analysis and design stays valid.
Central question: What goes where?
In the end, need to put things somewhere, or risk
unmanageable global namespace.
15
New Objects
Previously:
“Objects are characterized by state, identity,
and behavior.” (Booch)
Now:
Eliminate or reduce mutable state.
Structural equality instead of reference identity.
Concentrate on functionality (behavior)
Can FP and OOP be combined?
16
OOP
FP
Lot’s of misunderstandings in both
communities
How many OOP
people see FP
How many FP
people see OOP
17
Would prefer it to be like this:
But need to get rid of some baggage
first
Bridging the Gap
• Scala acts as a bridge between
the two paradigms.
• To do this, it tries to be:
– orthogonal
– expressive
– un-opinionated
• It naturally adapts to many
different programming styles.
18
A Question of Style
• Because Scala admits such a broad range of styles,
the question is which one to pick?
• But what is it then? I expect that a new fusion of
functional and object-oriented will emerge.
19
Certainly, Scala is:
– Not a better Java
– Not a Haskell on the
JVM
Some Guidelines
20
#1 Keep it Simple
21
#2 Don’t pack too much in one expression
• I sometimes see stuff like this:
jp.getRawClasspath.filter(
_.getEntryKind == IClasspathEntry.CPE_SOURCE).
iterator.flatMap(entry =>
flatten(ResourcesPlugin.getWorkspace.
getRoot.findMember(entry.getPath)))
• It’s amazing what you can get done in a single
statement.
• But that does not mean you have to do it.
22
Find meaningful names
• There’s a lot of value in meaningful names.
• Easy to add them using inline vals and defs.
val sources = jp.getRawClasspath.filter(
_.getEntryKind == IClasspathEntry.CPE_SOURCE)
def workspaceRoot =
ResourcesPlugin.getWorkspace.getRoot
def filesOfEntry(entry: Set[File]) =
flatten(workspaceRoot.findMember(entry.getPath)
sources.iterator flatMap filesOfEntry
23
#3 Prefer Functional
24
Prefer Functional ...
• By default:
– use vars, not vals.
– use recursions or combinators, not loops.
– use immutable collections
– concentrate on transformations, not CRUD.
• When to deviate from the default:
– Sometimes, mutable gives better performance.
– Sometimes (but not that often!) it adds convenience.
25
#4 ... But don’t diabolize local state
Why does mutable state lead to complexity?
It interacts with different program parts in ways that are
hard to track.
=> Local state is less harmful than global state.
26
“Var” Shortcuts
Example:
var interfaces = parseClassHeader()....
if (isAnnotation) interfaces += ClassFileAnnotation
Could have written:
val parsedIfaces = parseClassHeader()
val interfaces =
if (isAnnotation) parsedIfaces + ClassFileAnnotation
else parsedIfaces
But this is not necessarily clearer.
27
A Question of Naming
As so often, it comes down to naming.
Do the additional intermediate results of the functional solution
help understanding?
val parsedIfaces = parseClassHeader()
val interfaces =
if (isAnnotation) parsedIfaces + ClassFileAnnotation
else parsedIfaces
28
More local state examples
• Here’s another example where local state is useful.
• Say you have a sequence of items with price and
discount attributes.
• Compute separately the sums of all prices and all
discounts
val totalPrice = items.map(_.price).sum
val totalDiscount = items.map(_.discount).sum
• Now, do the same with just one sequence traversal
(maybe because items is an iterator).
29
More local state examples
The canonical functional solution uses a foldLeft:
val (totalPrice, totalDiscount) =
items.foldLeft((0.0, 0.0)) {
case ((tprice, tdiscount), item) =>
(tprice + item.price,
tdiscount + item.discount)
}
}
Whereas the canonical imperative solution looks like this:
var totalPrice, totalDiscount = 0.0
for (item <- items) {
totalPrice += item.price
totalDiscount += item.discount
}
30
#5 Careful with mutable objects
Mutable objects tend to encapsulate global
state.
“Encapsulate” sounds good, but it does not
make the global state go away!
=> Still a lot of potential for complex
entanglements.
31
When is an Object Mutable?
If it contains vars?
But then how about this one:
class BufferProxy[T](buf: ArrayBuffer[T]) {
def put(x: T) = buf.append(x)
def length = buf.length
}
32
When is an Object Mutable?
Or this one:
class Memo[T, U](fn: T => U) {
val memo = new mutable.WeakHashMap[T, U]
def apply(x: T) = memo.getOrElseUpdate(x, fn(x))
}
An object is mutable if its (functional) behavior depends on its
history.
new Memo { i: Int => i + 1 } // immutable
var ctr = 0
new Memo { i: Int => ctr += i; ctr } // mutable
33
#6 Don’t stop improving too early
• You often can shrink code by a factor of 10, and make it
more legible at the same time.
• But the cleanest and most elegant solutions do not
always come to mind at once.
• That’s OK. It’s great to experience the pleasure to find a
better solution multiple times.
So, keep going ...
34
Choices
35
Choice #1: Infix vs “.”
Scala unifies operators and method calls.
Every operator is a method
Every method with at least one parameter can be used as an
infix operator.
How do you choose?
items + 10 or items.+(10) ?
xs map f or xs.map(f) ?
xs flatMap or xs.flatMap(fun) ?
fun filterNot .filterNot(isZero)
isZero groupBy keyFn .groupBy(keyFn)
36
Infix vs “.”
• If the method name is symbolic, always use infix.
• For alphanumeric method names, one can use infix if
there is only one alphanumeric operator in the
expression
mapping add filter
• But prefer “.method(...)” for chained operators:
mapping.add(filter).map(second).flatMap(third)
xs.map(f).mkString
37
Choice #2: Alphabetic vs Symbolic
Scala unifies operators and methods.
Every operator is a method.
Identifiers can be alphanumeric or symbolic.
How do you choose?
xs map f or xs *|> f ?
vector + mx or vector add mx ?
(xs.foldLeft(z))(op) or (z /: xs)(op) ?
UNDEFINED or ??? ?
38
Alphabetic vs Symbolic
Recommentation: Use symbolic only if
1. Meaning is understood by your target audience
2. Operator is standard in application domain, or
3. You would like to draw attention to the operator
(symbolic usually sticks out more than alphabetic).
(Reason 3 is risky)
39
Choice #3: Loop, recursion or combinators?
Often, for the same functionality you can use a loop:
var i = 0
while (i < limit && !qualifies(i)) i += 1
i
Or you could use recursion:
def recur(i: Int): Int =
if (i >= limit || qualifies(i)) i else recur(i + 1)
recur(0)
Or you could use predefined combinators:
(0 until length).find(qualifies).getOrElse(length)
How do you choose?
40
How About This One:
xs map f ?
var buf = new ListBuffer[String]
for (x <- xs) buf += f(x)
xs.toList ?
def recur(xs: List[String]) = xs match {
case x :: xs1 => f(x) :: recur(xs1)
case Nil => Nil
} ?
41
And How About This One:
42
xs.grouped(2).toList.map {
case List(x, y) => x * y
}
var buf = new ListBuffer[Int]
var ys = xs
while (ys.nonEmpty) {
buf += ys(0) * ys(1)
ys = ys.tail.tail
}
def recur(xs: List[Int]): List[Int] = xs match {
case x1 :: x2 :: xs1 => (x1 * x2) :: recur(xs1)
case Nil => Nil
}
recur(xs)
Clearly the worst
Great if you know the combinators...
... and everybody else does as well.
Easier to grasp for newcomers,
and they tend to be more efficient as well.
Why does Scala have all three?
• Combinators: Easiest to use, are done in the library.
• Recursive functions: bedrock of FP
• Pattern matching: Much clearer and safer than tests and
selections.
• Loops: Because they are familiar, and sometimes are
the simplest solution.
43
Recommendation
• Consider using combinators first.
• If this becomes too tedious, or efficiency is a big
concern, fall back on tail-recursive functions.
• Loops can be used in simple cases, or when the
computation inherently modifies state.
44
Choice #4: Procedures or “=“
Scala has special syntax for Unit-returning procedures.
def swap[T](arr: Array[T], i: Int, j: Int) {
val t = arr(i); arr(i) = arr(j); arr(j) = t
}
or:
def swap[T](arr: Array[T], i: Int, j: Int): Unit = {
val t = arr(i); arr(i) = arr(j); arr(j) = t
}
Which do you choose?
45
Why Scala has both
• Historical accident.
• I was concerned to have to explain Unit too early to Java
programmers.
• Problem: This trades simplicity for ease of use/familiarity.
• Also, opens up a bad trap:
def swap(arr: Array[T], i: Int, j: Int): Unit {
val t = arr(i); arr(i) = arr(j); arr(j) = t
}
46
Recommendation
Don’t use procedure syntax.
47
Choice #5: Private vs nested
Say you have an outer method that uses a helper method for
some of its functionality:
def outer(owner: Symbol) = {
def isJava(sym: Symbol): Boolean = sym hasFlag JAVA
if (symbols exists isJava) ...
...
}
Do you write isJava inline, or as a separate private method?
48
Private as an alternative
private def isJava(sym: Symbol): Boolean =
sym hasFlag JAVA
def outer() = {
if (symbols exists isJava) ...
...
}
• Advantahe
49
When to Use Nesting
You definitely want to nest if that way you avoid passing
parameters by capturing a value in the environment.
def outer(owner: Symbol) = {
def isJava(sym: Symbol): Boolean =
(sym hasFlag JAVA) || owner.isJava
if (symbols exists isJava) ...
...
}
But if you do not capture anything it becomes harder to
verify that fact if you have to scan lots of nested code.
50
Recommendation
1. Prefer nesting if you can save on parameters.
2. Prefer nesting for small functions, even if nothing is
captured.
3. Don’t nest many levels deep.
51
Choice #6:
Pattern matching vs dynamic dispatch
Say you have a class hierarchy of shapes.
class Shape
case class Circle(center: Point, radius: Double)
extends Shape
case class Rectangle(ll: Point, ur: Point)
extends Shape
case class Point(x: Double, y: Double)
extends Shape
and you want to write a method to compute the area of a
shape.
52
Alternative 1: Pattern matching
Could could write a single method area and match over all
possible shapes:
def area(s: Shape): Double = s match {
case Circle(_, r) =>
math.pi * r * r
case Rectangle(ll, ur) =>
(ur.x – ll.x) * (ur.y – ll.y)
case Point(_, _) =>
0
}
53
Alternative 2: Dynamic Dispatch
Or, you could add an area method to each Shape class.
class Shape {
def area: Double
}
case class Circle(center: Point, radius: Double)
extends Shape {
def area = pi * radius * radius
}
case class Rectangle(ll: Point, ur: Point)
extends Shape {
def area = (ur.x – ll.x) * (ur.y – ll.y)
}
Which do you choose?
54
Why Scala has Both
Pattern matching: functional, convenient
Dynamic dispatch: core mechanism for extensible systems.
55
Recommendation
• It depends whether your system should be extensible or
not.
• If you foresee extensions with new data alternatives,
choose dynamic dispatch.
• If you foresee adding new methods later, choose pattern
matching.
• If the system is complex and closed, also choose pattern
matching.
• What if you want to extend in both dimensions?
56
Extensibility in both dimensions
Here’s one way to do it:
class ShapeHandler {
def area(s: Shape) = s match {
...
}
}
class ExtraShapeHandler {
def area(s: Shape) = s match {
case Triangle(...) => ...
case _ => super.area(s)
}
“The expression problem”.
57
Choice #7:
Type parameters vs abstract members
Do you choose
class Animal[+Food] class Animal {
or type Food
def p: Animal[Food] def p: Animal {
type Food = this.Food
}
}
class Cow class Cow extends Animal {
extends Animal[Grass] type Food <: Grass
}
?
58
Type parameters look more concise here.
But: Less pleasing to talk about Animal’s irrespective of
their food.
Animal[_] vs Animal
Also, sometimes parameters need to be duplicated.
And, it gets complicated when there are bounds that refer
to each other.
59
Parameter Duplication
The Scala library contains these traits:
trait Map[Key, Value] { ... }
trait SynchronizedMap[Key, Value]
extends Map[Key, Value]
Duplication! And it does not stop there:
new HashMap[String, Int] with
SynchronizedMap[String, Int]
60
Abstract Members avoid Duplication
If Map were defined like this:
class Map {
type Key
type Value
}
we could define SynchronizedMap like this:
class SynchronizedMap extends Map
and we could create a map like this:
new HashMap with SynchronizedMap {
type Key = String
type Value = Int
}
61
What About Value Parameters?
The same question exists for value parameters, but we
have better tools to reach a synthesis.
Example: Should I write
class C(x: Int) or abstract class C {
val x: Int
} ?
Can combine both using a val parameter.
class C(val x: Int)
62
Type Parameters = Type Members?
It would be nice if we could apply the same trick to type
parameters:
class Map[type Key, type Value]
class SynchronizedMap extends Map
new Map[String, Int] with SynchronizedMap
This is currently not supported.
But we are working on a design that would let us do that.
63
Recommendation
1. By default, use type parameters.
2. Use abstract type members if the normal use case is
generic in the type.
3. (That, is, avoid wildcards such as Animal[_]
64
The Future
Goal:
Make Scala the language of choice for smart kids
Bring out the simplicity in Scala
Focus on the beautiful side, avoid over-complications
65
Thank You

Contenu connexe

Tendances

Functional Programming In Practice
Functional Programming In PracticeFunctional Programming In Practice
Functional Programming In PracticeMichiel Borkent
 
Introductiontoprogramminginscala
IntroductiontoprogramminginscalaIntroductiontoprogramminginscala
IntroductiontoprogramminginscalaAmuhinda Hungai
 
Scala categorytheory
Scala categorytheoryScala categorytheory
Scala categorytheoryKnoldus Inc.
 
20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdasshinolajla
 
A Tour Of Scala
A Tour Of ScalaA Tour Of Scala
A Tour Of Scalafanf42
 
BayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore HaskellBayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore HaskellBryan O'Sullivan
 
Functional Programming in Scala: Notes
Functional Programming in Scala: NotesFunctional Programming in Scala: Notes
Functional Programming in Scala: NotesRoberto Casadei
 
Python Programming - II. The Basics
Python Programming - II. The BasicsPython Programming - II. The Basics
Python Programming - II. The BasicsRanel Padon
 
Scala eXchange opening
Scala eXchange openingScala eXchange opening
Scala eXchange openingMartin Odersky
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
 
Hey! There's OCaml in my Rust!
Hey! There's OCaml in my Rust!Hey! There's OCaml in my Rust!
Hey! There's OCaml in my Rust!Kel Cecil
 
Introduction to join calculus
Introduction to join calculusIntroduction to join calculus
Introduction to join calculusSergei Winitzki
 
stacks and queues class 12 in c++
stacks and  queues class 12 in c++stacks and  queues class 12 in c++
stacks and queues class 12 in c++Khushal Mehta
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with ScalaDenis
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingMario Fusco
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdfHiroshi Ono
 

Tendances (20)

Functional Programming In Practice
Functional Programming In PracticeFunctional Programming In Practice
Functional Programming In Practice
 
Introductiontoprogramminginscala
IntroductiontoprogramminginscalaIntroductiontoprogramminginscala
Introductiontoprogramminginscala
 
Scala categorytheory
Scala categorytheoryScala categorytheory
Scala categorytheory
 
Scala Intro
Scala IntroScala Intro
Scala Intro
 
20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas
 
A Tour Of Scala
A Tour Of ScalaA Tour Of Scala
A Tour Of Scala
 
BayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore HaskellBayFP: Concurrent and Multicore Haskell
BayFP: Concurrent and Multicore Haskell
 
Functional Programming in Scala: Notes
Functional Programming in Scala: NotesFunctional Programming in Scala: Notes
Functional Programming in Scala: Notes
 
Python Programming - II. The Basics
Python Programming - II. The BasicsPython Programming - II. The Basics
Python Programming - II. The Basics
 
Scala eXchange opening
Scala eXchange openingScala eXchange opening
Scala eXchange opening
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Hey! There's OCaml in my Rust!
Hey! There's OCaml in my Rust!Hey! There's OCaml in my Rust!
Hey! There's OCaml in my Rust!
 
Introduction to join calculus
Introduction to join calculusIntroduction to join calculus
Introduction to join calculus
 
Quick introduction to scala
Quick introduction to scalaQuick introduction to scala
Quick introduction to scala
 
stacks and queues class 12 in c++
stacks and  queues class 12 in c++stacks and  queues class 12 in c++
stacks and queues class 12 in c++
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with Scala
 
Joy of scala
Joy of scalaJoy of scala
Joy of scala
 
Why we cannot ignore Functional Programming
Why we cannot ignore Functional ProgrammingWhy we cannot ignore Functional Programming
Why we cannot ignore Functional Programming
 
Getting Started With Scala
Getting Started With ScalaGetting Started With Scala
Getting Started With Scala
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 

Similaire à ScalaDays 2013 Keynote Speech by Martin Odersky

Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With ScalaKnoldus Inc.
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationMartin Odersky
 
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...Andrew Phillips
 
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Andrew Phillips
 
Functional programming with Scala
Functional programming with ScalaFunctional programming with Scala
Functional programming with ScalaNeelkanth Sachdeva
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdfHiroshi Ono
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdfHiroshi Ono
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdfHiroshi Ono
 
About Functional Programming
About Functional ProgrammingAbout Functional Programming
About Functional ProgrammingAapo Kyrölä
 
LISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love ParanthesesLISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love ParanthesesDominic Graefen
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Martin Odersky
 
Go Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional ProgrammingGo Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional ProgrammingLex Sheehan
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinayViplav Jain
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaScala Italy
 
flatMap Oslo presentation slides
flatMap Oslo presentation slidesflatMap Oslo presentation slides
flatMap Oslo presentation slidesMartin Odersky
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...Philip Schwarz
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2Philip Schwarz
 

Similaire à ScalaDays 2013 Keynote Speech by Martin Odersky (20)

Functional Programming With Scala
Functional Programming With ScalaFunctional Programming With Scala
Functional Programming With Scala
 
Scala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentationScala - The Simple Parts, SFScala presentation
Scala - The Simple Parts, SFScala presentation
 
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
BASE Meetup: "Analysing Scala Puzzlers: Essential and Accidental Complexity i...
 
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
Scala Up North: "Analysing Scala Puzzlers: Essential and Accidental Complexit...
 
Functional programming with Scala
Functional programming with ScalaFunctional programming with Scala
Functional programming with Scala
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
About Functional Programming
About Functional ProgrammingAbout Functional Programming
About Functional Programming
 
LISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love ParanthesesLISP: How I Learned To Stop Worrying And Love Parantheses
LISP: How I Learned To Stop Worrying And Love Parantheses
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Go Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional ProgrammingGo Beyond Higher Order Functions: A Journey into Functional Programming
Go Beyond Higher Order Functions: A Journey into Functional Programming
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinay
 
Devoxx
DevoxxDevoxx
Devoxx
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of Scala
 
Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
flatMap Oslo presentation slides
flatMap Oslo presentation slidesflatMap Oslo presentation slides
flatMap Oslo presentation slides
 
Flatmap
FlatmapFlatmap
Flatmap
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala Part 2 ...
 
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
Folding Unfolded - Polyglot FP for Fun and Profit - Haskell and Scala - Part 2
 

Dernier

Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 

Dernier (20)

Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 

ScalaDays 2013 Keynote Speech by Martin Odersky

  • 2. This Talk I’ll argue that we are at a transition period between two programming paradigms: Imperative/OOP  Functional. In the end, we will see a fusion of these. In light of this development, many questions of programming techniques and style have to be revisited. 2
  • 3. How OOP got started First popular OO language: Simula 67 Second popular OO language: Smalltalk 3
  • 4. Why Did OOP become popular? Encapsulation? Code Re-use? Dynamic Binding Dependency inversion? Liskov substition principle? Open-closed principle? It was because of the things you could do with OOP! 4 No Don’t think so Not directly Came much later You gotta be kidding!
  • 5. How OOP got started Traditional approach: Linked List Two cases: Empty, NonEmpty Unbounded number of operations: – map – reverse – print – get elem – insert – ... 5
  • 6. How OOP got started New challenge: Simulation Fixed number of operations: nextStep toString aggregate Unbounded number of implementations: Car, Road, Molecule, Cell, Person, Building, City, ... 6
  • 7. How OOP got started New challenge: GUI widgets Fixed number of operations: redraw boundingRectangle move Unbounded number of implementations: Window, Menu, Letter, Shape, Curve, Image, Video, ... 7
  • 8. What Simulation and GUIs have in common Both need a way to execute a fixed API with an unknown implementation. It’s possible to do this in a procedural language such as C. But it’s too cumbersome, so people wanted object-oriented languages instead. 8
  • 9. What does this have to do with FP? Just like OOP did then, FP has lots of methodological advantages: – Fewer errors – Better modularity – Higher-level abstractions – Shorter code – Increased developer productivity But these alone are not enough for mainstream adoption (after all FP has been around for 50 years) Need a catalyzer, something that sparks initial adoption until the other advantages become clear to everyone. 9
  • 10. FP on the Rise • In Computer Science: Compare #attendees of OOP conferences: OOPSLA, ECOOP with FP conference: ICFP 12 years ago : ECOOP ~ 3 x ICFP OOPSLA ~ 10 x ICFP 2012 : ICFP ~ 2 x ECOOP OOPSLA stopped existing as independent conf. • Developer interest: over 100’000 signed up for our #progfun course Functional Programming Principles in Scala. 10
  • 11. A Catalyzer • Two forces driving software complexity: • Multicore (= parallel programming) • Cloud computing (= distributed programming) • Current languages and frameworks have trouble keeping up (locks/threads don’t scale) • Need better tools with the right level of abstraction 11
  • 12. Triple Challenge Parallel – how to make use of multicore, GPUs, clusters? Async – how to deal with asynchronous events Distributed – how to deal with delays and failures? Mutable state is a liability for each one of these! – Cache coherence – Races – Versioning 12
  • 13. The Essence of Functional Programming 13 Concentrate on transformations of immutable values instead of stepwise modifications of mutable state.
  • 14. 14 What about Objects? So, should we forget OO and all program in functional programming languages? No! What the industry learned about OO decomposition in analysis and design stays valid. Central question: What goes where? In the end, need to put things somewhere, or risk unmanageable global namespace.
  • 15. 15 New Objects Previously: “Objects are characterized by state, identity, and behavior.” (Booch) Now: Eliminate or reduce mutable state. Structural equality instead of reference identity. Concentrate on functionality (behavior)
  • 16. Can FP and OOP be combined? 16 OOP FP Lot’s of misunderstandings in both communities How many OOP people see FP How many FP people see OOP
  • 17. 17 Would prefer it to be like this: But need to get rid of some baggage first
  • 18. Bridging the Gap • Scala acts as a bridge between the two paradigms. • To do this, it tries to be: – orthogonal – expressive – un-opinionated • It naturally adapts to many different programming styles. 18
  • 19. A Question of Style • Because Scala admits such a broad range of styles, the question is which one to pick? • But what is it then? I expect that a new fusion of functional and object-oriented will emerge. 19 Certainly, Scala is: – Not a better Java – Not a Haskell on the JVM
  • 21. #1 Keep it Simple 21
  • 22. #2 Don’t pack too much in one expression • I sometimes see stuff like this: jp.getRawClasspath.filter( _.getEntryKind == IClasspathEntry.CPE_SOURCE). iterator.flatMap(entry => flatten(ResourcesPlugin.getWorkspace. getRoot.findMember(entry.getPath))) • It’s amazing what you can get done in a single statement. • But that does not mean you have to do it. 22
  • 23. Find meaningful names • There’s a lot of value in meaningful names. • Easy to add them using inline vals and defs. val sources = jp.getRawClasspath.filter( _.getEntryKind == IClasspathEntry.CPE_SOURCE) def workspaceRoot = ResourcesPlugin.getWorkspace.getRoot def filesOfEntry(entry: Set[File]) = flatten(workspaceRoot.findMember(entry.getPath) sources.iterator flatMap filesOfEntry 23
  • 25. Prefer Functional ... • By default: – use vars, not vals. – use recursions or combinators, not loops. – use immutable collections – concentrate on transformations, not CRUD. • When to deviate from the default: – Sometimes, mutable gives better performance. – Sometimes (but not that often!) it adds convenience. 25
  • 26. #4 ... But don’t diabolize local state Why does mutable state lead to complexity? It interacts with different program parts in ways that are hard to track. => Local state is less harmful than global state. 26
  • 27. “Var” Shortcuts Example: var interfaces = parseClassHeader().... if (isAnnotation) interfaces += ClassFileAnnotation Could have written: val parsedIfaces = parseClassHeader() val interfaces = if (isAnnotation) parsedIfaces + ClassFileAnnotation else parsedIfaces But this is not necessarily clearer. 27
  • 28. A Question of Naming As so often, it comes down to naming. Do the additional intermediate results of the functional solution help understanding? val parsedIfaces = parseClassHeader() val interfaces = if (isAnnotation) parsedIfaces + ClassFileAnnotation else parsedIfaces 28
  • 29. More local state examples • Here’s another example where local state is useful. • Say you have a sequence of items with price and discount attributes. • Compute separately the sums of all prices and all discounts val totalPrice = items.map(_.price).sum val totalDiscount = items.map(_.discount).sum • Now, do the same with just one sequence traversal (maybe because items is an iterator). 29
  • 30. More local state examples The canonical functional solution uses a foldLeft: val (totalPrice, totalDiscount) = items.foldLeft((0.0, 0.0)) { case ((tprice, tdiscount), item) => (tprice + item.price, tdiscount + item.discount) } } Whereas the canonical imperative solution looks like this: var totalPrice, totalDiscount = 0.0 for (item <- items) { totalPrice += item.price totalDiscount += item.discount } 30
  • 31. #5 Careful with mutable objects Mutable objects tend to encapsulate global state. “Encapsulate” sounds good, but it does not make the global state go away! => Still a lot of potential for complex entanglements. 31
  • 32. When is an Object Mutable? If it contains vars? But then how about this one: class BufferProxy[T](buf: ArrayBuffer[T]) { def put(x: T) = buf.append(x) def length = buf.length } 32
  • 33. When is an Object Mutable? Or this one: class Memo[T, U](fn: T => U) { val memo = new mutable.WeakHashMap[T, U] def apply(x: T) = memo.getOrElseUpdate(x, fn(x)) } An object is mutable if its (functional) behavior depends on its history. new Memo { i: Int => i + 1 } // immutable var ctr = 0 new Memo { i: Int => ctr += i; ctr } // mutable 33
  • 34. #6 Don’t stop improving too early • You often can shrink code by a factor of 10, and make it more legible at the same time. • But the cleanest and most elegant solutions do not always come to mind at once. • That’s OK. It’s great to experience the pleasure to find a better solution multiple times. So, keep going ... 34
  • 36. Choice #1: Infix vs “.” Scala unifies operators and method calls. Every operator is a method Every method with at least one parameter can be used as an infix operator. How do you choose? items + 10 or items.+(10) ? xs map f or xs.map(f) ? xs flatMap or xs.flatMap(fun) ? fun filterNot .filterNot(isZero) isZero groupBy keyFn .groupBy(keyFn) 36
  • 37. Infix vs “.” • If the method name is symbolic, always use infix. • For alphanumeric method names, one can use infix if there is only one alphanumeric operator in the expression mapping add filter • But prefer “.method(...)” for chained operators: mapping.add(filter).map(second).flatMap(third) xs.map(f).mkString 37
  • 38. Choice #2: Alphabetic vs Symbolic Scala unifies operators and methods. Every operator is a method. Identifiers can be alphanumeric or symbolic. How do you choose? xs map f or xs *|> f ? vector + mx or vector add mx ? (xs.foldLeft(z))(op) or (z /: xs)(op) ? UNDEFINED or ??? ? 38
  • 39. Alphabetic vs Symbolic Recommentation: Use symbolic only if 1. Meaning is understood by your target audience 2. Operator is standard in application domain, or 3. You would like to draw attention to the operator (symbolic usually sticks out more than alphabetic). (Reason 3 is risky) 39
  • 40. Choice #3: Loop, recursion or combinators? Often, for the same functionality you can use a loop: var i = 0 while (i < limit && !qualifies(i)) i += 1 i Or you could use recursion: def recur(i: Int): Int = if (i >= limit || qualifies(i)) i else recur(i + 1) recur(0) Or you could use predefined combinators: (0 until length).find(qualifies).getOrElse(length) How do you choose? 40
  • 41. How About This One: xs map f ? var buf = new ListBuffer[String] for (x <- xs) buf += f(x) xs.toList ? def recur(xs: List[String]) = xs match { case x :: xs1 => f(x) :: recur(xs1) case Nil => Nil } ? 41
  • 42. And How About This One: 42 xs.grouped(2).toList.map { case List(x, y) => x * y } var buf = new ListBuffer[Int] var ys = xs while (ys.nonEmpty) { buf += ys(0) * ys(1) ys = ys.tail.tail } def recur(xs: List[Int]): List[Int] = xs match { case x1 :: x2 :: xs1 => (x1 * x2) :: recur(xs1) case Nil => Nil } recur(xs) Clearly the worst Great if you know the combinators... ... and everybody else does as well. Easier to grasp for newcomers, and they tend to be more efficient as well.
  • 43. Why does Scala have all three? • Combinators: Easiest to use, are done in the library. • Recursive functions: bedrock of FP • Pattern matching: Much clearer and safer than tests and selections. • Loops: Because they are familiar, and sometimes are the simplest solution. 43
  • 44. Recommendation • Consider using combinators first. • If this becomes too tedious, or efficiency is a big concern, fall back on tail-recursive functions. • Loops can be used in simple cases, or when the computation inherently modifies state. 44
  • 45. Choice #4: Procedures or “=“ Scala has special syntax for Unit-returning procedures. def swap[T](arr: Array[T], i: Int, j: Int) { val t = arr(i); arr(i) = arr(j); arr(j) = t } or: def swap[T](arr: Array[T], i: Int, j: Int): Unit = { val t = arr(i); arr(i) = arr(j); arr(j) = t } Which do you choose? 45
  • 46. Why Scala has both • Historical accident. • I was concerned to have to explain Unit too early to Java programmers. • Problem: This trades simplicity for ease of use/familiarity. • Also, opens up a bad trap: def swap(arr: Array[T], i: Int, j: Int): Unit { val t = arr(i); arr(i) = arr(j); arr(j) = t } 46
  • 48. Choice #5: Private vs nested Say you have an outer method that uses a helper method for some of its functionality: def outer(owner: Symbol) = { def isJava(sym: Symbol): Boolean = sym hasFlag JAVA if (symbols exists isJava) ... ... } Do you write isJava inline, or as a separate private method? 48
  • 49. Private as an alternative private def isJava(sym: Symbol): Boolean = sym hasFlag JAVA def outer() = { if (symbols exists isJava) ... ... } • Advantahe 49
  • 50. When to Use Nesting You definitely want to nest if that way you avoid passing parameters by capturing a value in the environment. def outer(owner: Symbol) = { def isJava(sym: Symbol): Boolean = (sym hasFlag JAVA) || owner.isJava if (symbols exists isJava) ... ... } But if you do not capture anything it becomes harder to verify that fact if you have to scan lots of nested code. 50
  • 51. Recommendation 1. Prefer nesting if you can save on parameters. 2. Prefer nesting for small functions, even if nothing is captured. 3. Don’t nest many levels deep. 51
  • 52. Choice #6: Pattern matching vs dynamic dispatch Say you have a class hierarchy of shapes. class Shape case class Circle(center: Point, radius: Double) extends Shape case class Rectangle(ll: Point, ur: Point) extends Shape case class Point(x: Double, y: Double) extends Shape and you want to write a method to compute the area of a shape. 52
  • 53. Alternative 1: Pattern matching Could could write a single method area and match over all possible shapes: def area(s: Shape): Double = s match { case Circle(_, r) => math.pi * r * r case Rectangle(ll, ur) => (ur.x – ll.x) * (ur.y – ll.y) case Point(_, _) => 0 } 53
  • 54. Alternative 2: Dynamic Dispatch Or, you could add an area method to each Shape class. class Shape { def area: Double } case class Circle(center: Point, radius: Double) extends Shape { def area = pi * radius * radius } case class Rectangle(ll: Point, ur: Point) extends Shape { def area = (ur.x – ll.x) * (ur.y – ll.y) } Which do you choose? 54
  • 55. Why Scala has Both Pattern matching: functional, convenient Dynamic dispatch: core mechanism for extensible systems. 55
  • 56. Recommendation • It depends whether your system should be extensible or not. • If you foresee extensions with new data alternatives, choose dynamic dispatch. • If you foresee adding new methods later, choose pattern matching. • If the system is complex and closed, also choose pattern matching. • What if you want to extend in both dimensions? 56
  • 57. Extensibility in both dimensions Here’s one way to do it: class ShapeHandler { def area(s: Shape) = s match { ... } } class ExtraShapeHandler { def area(s: Shape) = s match { case Triangle(...) => ... case _ => super.area(s) } “The expression problem”. 57
  • 58. Choice #7: Type parameters vs abstract members Do you choose class Animal[+Food] class Animal { or type Food def p: Animal[Food] def p: Animal { type Food = this.Food } } class Cow class Cow extends Animal { extends Animal[Grass] type Food <: Grass } ? 58
  • 59. Type parameters look more concise here. But: Less pleasing to talk about Animal’s irrespective of their food. Animal[_] vs Animal Also, sometimes parameters need to be duplicated. And, it gets complicated when there are bounds that refer to each other. 59
  • 60. Parameter Duplication The Scala library contains these traits: trait Map[Key, Value] { ... } trait SynchronizedMap[Key, Value] extends Map[Key, Value] Duplication! And it does not stop there: new HashMap[String, Int] with SynchronizedMap[String, Int] 60
  • 61. Abstract Members avoid Duplication If Map were defined like this: class Map { type Key type Value } we could define SynchronizedMap like this: class SynchronizedMap extends Map and we could create a map like this: new HashMap with SynchronizedMap { type Key = String type Value = Int } 61
  • 62. What About Value Parameters? The same question exists for value parameters, but we have better tools to reach a synthesis. Example: Should I write class C(x: Int) or abstract class C { val x: Int } ? Can combine both using a val parameter. class C(val x: Int) 62
  • 63. Type Parameters = Type Members? It would be nice if we could apply the same trick to type parameters: class Map[type Key, type Value] class SynchronizedMap extends Map new Map[String, Int] with SynchronizedMap This is currently not supported. But we are working on a design that would let us do that. 63
  • 64. Recommendation 1. By default, use type parameters. 2. Use abstract type members if the normal use case is generic in the type. 3. (That, is, avoid wildcards such as Animal[_] 64
  • 65. The Future Goal: Make Scala the language of choice for smart kids Bring out the simplicity in Scala Focus on the beautiful side, avoid over-complications 65