1. Programming Paradigms & Constructs
Nicolas Demengel 2011, July 7th
www.xebia.fr / blog.xebia.fr 1
2. Inspiration
Ruby, Io, Prolog, Scala,
Erlang, Clojure, Haskell
Presentation of those
languages' main features
Exercises
Good start...
but not enough!
www.xebia.fr / blog.xebia.fr 2
3. Agenda
Talk
▶ Definitions and Examples
▶ Laptops allowed! (and encouraged)
Hands On!
▶ Choose one or several exercises to solve
Retrospective
▶ Comparison of solutions to some exercises
▶ Feelings about this or that feature/language
www.xebia.fr / blog.xebia.fr 3
4. Material
Image for VirtualBox
Under your home:
▶ A folder for each language
▶ Simple examples of the language
features
▶ HOWTO: instructions for compiling
or interpreting the examples
▶ Solved exercises
▶ Unresolved problems
www.xebia.fr / blog.xebia.fr 4
5. Describing A Language
Paradigm
▶ Style, concepts, abstractions, computation
Typing
▶ Constraints applied to values
▶ Operations provided for kinds of values
Constructs
▶ Decision constructs, data structures, advanced features
Syntax
▶ Rules, expressiveness
Ecosystem, …
▶ Out of scope
www.xebia.fr / blog.xebia.fr 5
6. The Four Main Paradigms (1/4)
Imperative (Procedural)
▶ “First do this, next do that” => recipe
▶ Control structures and procedures
▶ Hard to organize
▶ Sensitive to small changes
Functional
▶ Theory of functions
▶ Given the same input, a function will produce the same output
▶ Immutable values, no side effect
▶ Higher-order functions
▶ Computation-oriented, suitable for data transformation
▶ Sometimes allows for proof of correctness
www.xebia.fr / blog.xebia.fr 6
7. The Four Main Paradigms (2/4)
Logic
▶ Build a knowledge base with facts and rules
▶ Query the program and let it infer solutions
▶ Adapted to knowledge extraction => IA
Object-Oriented
▶ Grouping of data and behavior
▶ Message passing between objects
▶ Inheritance and polymorphism
▶ Domain-oriented, adapted to large and evolutive programs
www.xebia.fr / blog.xebia.fr 7
8. The Four Main Paradigms (3/4)
A word about Prototype-based Programming
▶ A flavor of OO
▶ No classes, but still allows for inheritance via prototypes
▶ Naively put: a given object may be:
› an “instance” of another object (having it as prototype)
› a “class” of another object (being one of its prototypes)
▶ Very powerful! Example:
› a publication
› a newspaper
› Le Monde
› the July 7th edition of Le Monde
› my copy of the July 7th edition of Le Monde
› ...
www.xebia.fr / blog.xebia.fr 8
9. The Four Main Paradigms (4/4)
A language is not always tied to a given paradigm
▶ You can write OO or Functional programs in C
www.xebia.fr / blog.xebia.fr 9
10. The Four Main Paradigms (4/4)
A language is not always tied to a given paradigm
▶ You can write OO or Functional programs in C
Source: Pulp Fiction. Dir. Quentin Tarentino. Miramax Films. 1994. Film
www.xebia.fr / blog.xebia.fr 10
11. The Four Main Paradigms (4/4)
A language is not always tied to a given paradigm
▶ You can write OO or Functional programs in C
Source: Pulp Fiction. Dir. Quentin Tarentino. Miramax Films. 1994. Film
▶ You can write OO programs with a Functional language and vice-versa
▶ Some languages mixes paradigms (C++, Scala, ...)
There are many other paradigms
▶ Most of them are flavors of the four main ones
www.xebia.fr / blog.xebia.fr 11
12. The Main Languages That We Will See (1/2)
Erlang
▶ 1986, functional, dynamic, concurrent, fault-tolerant
▶ “Ericsson Language”
Haskell
▶ 1990, purely functional, static, lazy, “standard”
Ruby
▶ 1995, object-oriented and functional, dynamic
www.xebia.fr / blog.xebia.fr 12
13. The Main Languages That We Will See (2/2)
Scala
▶ 2003, object-oriented and functional, static, concurrent, on the JVM
Clojure
▶ 2007, functional, dynamic (code as data), concurrent, on the JVM
▶ Lisp dialect
www.xebia.fr / blog.xebia.fr 13
14. A Word About Prolog (1/3)
What we are used to: assignment
▶ X = 10 assign 10 to variable X
Prolog: Unification
▶ X = 10 given an unknown X, make 10 and X match (binding)
▶ X = 10 given a yet known X, does it match 10? (matching)
www.xebia.fr / blog.xebia.fr 14
15. A Word About Prolog (1/3)
What we are used to: assignment
▶ X = 10 assign 10 to variable X
Prolog: Unification
▶ X = 10 given an unknown X, make 10 and X match (binding)
▶ X = 10 given a yet known X, does it match 10? (matching)
▶ Basics of logic programming:
author(what_mad_universe, frederic_brown).
author(the_eyre_affair, jasper_fforde).
genre(what_mad_universe, science_fiction).
genre(the_eyre_affair, science_fiction).
genre(the_eyre_affair, comic_novel).
writes_genre(Author, Genre) :-
author(Book, Author),
genre(Book, Genre).
www.xebia.fr / blog.xebia.fr 15
16. A Word About Prolog (2/3)
|?- writes_genre(Who, science_fiction).
Who = frederic_brown ?
Who = jasper_fforde
yes
|?- writes_genre(frederic_brown, What).
What = science_fiction
yes
|?- writes_genre(jasper_fforde, comic_novel).
true
yes
|?- writes_genre(frederic_brown, comic_novel).
no
www.xebia.fr / blog.xebia.fr 16
17. A Word About Prolog (3/3)
Pattern matching
smallest([LonelyNumber], LonelyNumber).
smallest([Head|Tail], SmallestSoFar) :-
smallest(Tail, TailSmallest),
SmallestSoFar is min(Head, TailSmallest).
smallest([3, 1, 7], S). % S = 1
% more matching
smallest([], -1). % empty list
smallest(_, -1). % anything
smallest([_|[SecondItem|_]], -1) :-
SecondItem > 5, % guard
% ...
www.xebia.fr / blog.xebia.fr 17
20. Typing (1/6)
Static
▶ Type-checking at compile-time
▶ C, Java, Scala, Erlang, Haskell
Dynamic
▶ Type-checking at run-time
▶ JavaScript, Ruby, Python, Clojure
“Strong” / “Weak”
▶ What happens when types collide?
› 5 + 'a string'
▶ Can you subvert the type system?
› int an_int = (int) some_bytes;
▶ Few languages are totally “strongly” or “weakly” typed
www.xebia.fr / blog.xebia.fr 20
21. Typing (2/6)
Type Inference
▶ Deduction of the type of an expression at compile time
▶ Less boiler-plate code: eases writing and reading
▶ Haskell:
double x = x * 2
-- (Num a) => a -> a
double :: Integer -> Integer
double x = x * 2
-- Integer -> Integer
▶ Scala:
val ints = List(1, 2, 3)
// List[Int]
def addNumbers(first: Int, second: Int) = first + second
// equivalent to
def addNumbers(first: Int, second: Int): Int = first + second
www.xebia.fr / blog.xebia.fr 21
22. Typing (2/6)
Type Inference
▶ Deduction of the type of an expression at compile time
▶ Less boiler-plate code: eases writing and reading
▶ Java:
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
ints.add(3);
// Java 7
List<Integer> ints = new ArrayList<>();
// java.util.Arrays, unmodifiable
List<Integer> ints = asList(1, 2, 3);
// Guava, modifiable
List<Integer> ints = newArrayList(1, 2, 3);
www.xebia.fr / blog.xebia.fr 22
23. Typing (3/6)
Duck Typing
▶ Example (JS):
var car = {
startEngine: function() { /* vroom */ }
}
var blender = {
startEngine: function() { /* ouch my fingers! */ }
}
var thingsWithEngine = [car, blender];
for (thing in thingsWithEngine) {
thing.startEngine();
}
▶ If it walks like a duck and quacks like a duck, it’s a duck.
www.xebia.fr / blog.xebia.fr 23
24. Typing (3/6)
Duck Typing
▶ Example (JS):
var car = {
startEngine: function() { /* vroom */ }
}
var blender = {
startEngine: function() { /* ouch my fingers! */ }
}
var thingsWithEngine = [car, blender];
for (thing in thingsWithEngine) {
thing.startEngine();
}
▶ If it walks like a duck and quacks like a duck, it’s a duck.
And if it weighs the same as a duck...
www.xebia.fr / blog.xebia.fr 24
25. Typing (3/6)
A witch!
Source: Monthy Python and the Holy Grail.
Dir. Terry Gillian, Terry Jones. EMI Films.
1974. Film
www.xebia.fr / blog.xebia.fr 25
26. Typing (4/6)
Structural Typing: Type-safe Duck Typing
▶ Example (Scala):
class Car {
def startEngine = println("vroom")
}
class Blender {
def startEngine = println("ouch my fingers!")
}
type T = {def startEngine}
val thingsWithEngine = List[T](new Car(), new Blender())
thingsWithEngine.foreach(_.startEngine)
www.xebia.fr / blog.xebia.fr 26
27. Typing (5/6)
Mixins
▶ Interfaces with partial implementations
› Ruby:
module Printable
def print_me
print self.my_representation
end
end
class Thing
extend OtherThing # only one extension
include Printable
include Xxx # several inclusions
def my_representation
# ...
end
end
www.xebia.fr / blog.xebia.fr 27
29. Typing (6/6)
Out of scope but still interesting:
▶ Haskell's ad-hoc polymorphism
› type classes
› != subtype polymorphism or parametric polymorhism
› somehow equivalent to Java interfaces
www.xebia.fr / blog.xebia.fr 29
30. A Word About Dynamic Languages
Concision, productivity
▶ No need to declare value types
Meta-programming
▶ Ruby, Python, Groovy: message interception (method_missing)
▶ Io, Clojure: Deferred argument evaluation
▶ Perfect for DSL
Downside: safety
▶ Test it!
www.xebia.fr / blog.xebia.fr 30
31. Types we don't have in Java (1/5)
Symbols
▶ Sometimes called atoms or keywords: Prolog, Erlang
▶ Allows for naming things, for conveying meaning
▶ Clearer and more efficient than using strings or ints
› Ruby:
link_to("View Article", :controller => "articles", :action => "show")
› Prolog:
friend(laurel, hardy)
› Clojure:
(def product {:name "laser", :price 15})
› ...
www.xebia.fr / blog.xebia.fr 31
32. Types we don't have in Java (2/5)
Regex
▶ Scala:
val line = """Completed in 100ms (View: 25, DB: 75)
| 200 OK [http://example.com?params=here]"""
val LogEntry = """Completed in (d+)ms (View: (d+), DB: (d+))
| (d+) OK [http://example.com(.*)?.*""".r
www.xebia.fr / blog.xebia.fr 32
33. Types we don't have in Java (2/5)
Regex
▶ Scala:
val line = """Completed in 100ms (View: 25, DB: 75)
| 200 OK [http://example.com?params=here]"""
val LogEntry = """Completed in (d+)ms (View: (d+), DB: (d+))
| (d+) OK [http://example.com(.*)?.*""".r
val LogEntry(totalTime, viewTime, dbTime, responseCode, uri) = line
// result
totalTime: String = 100
viewTime: String = 25
dbTime: String = 75
responseCode: String = 200
uri: String = ""
www.xebia.fr / blog.xebia.fr 33
34. Types we don't have in Java (2/5)
Regex
▶ Scala:
val line = """Completed in 100ms (View: 25, DB: 75)
| 200 OK [http://example.com?params=here]"""
val LogEntry = """Completed in (d+)ms (View: (d+), DB: (d+))
| (d+) OK [http://example.com(.*)?.*""".r
val LogEntry(totalTime, viewTime, dbTime, responseCode, uri) = line
// result
totalTime: String = 100
viewTime: String = 25
dbTime: String = 75
responseCode: String = 200
uri: String = ""
Source.fromFile(logFile).getLines.collect { _ match {
case LogEntry(tt, vt, dbt, rc, uri) => println(rc)
case OtherPattern(var1, var2) => // …
case _ =>
}
}
www.xebia.fr / blog.xebia.fr 34
35. Types we don't have in Java (3/5)
XML
▶ Scala:
val things = <things>
<movie genre="action">Pirates of the Caribbean</movie>
<movie genre="fairytale">Edward Scissorhands</movie>
<book genre={ genre }>{ title }</book>
</things>
things "movie"
(things "@genre")(1).text
things "movie" find { node: Node => (node "@genre").text == "action" }
www.xebia.fr / blog.xebia.fr 35
36. Types we don't have in Java (3/5)
XML
▶ Scala:
val things = <things>
<movie genre="action">Pirates of the Caribbean</movie>
<movie genre="fairytale">Edward Scissorhands</movie>
<book genre={ genre }>{ title }</book>
</things>
things "movie"
(things "@genre")(1).text
things "movie" find { node: Node => (node "@genre").text == "action" }
(things "_").foreach { _ match {
case <movie>{ title }</movie> => println(title)
case <book>{ _ }</book> => println("book")
case _ =>
}
}
www.xebia.fr / blog.xebia.fr 36
37. Types we don't have in Java (4/5)
Ranges
▶ Ruby:
myArray[1..3] (1..3).to_a (1..21).each{|n| print n}
▶ Scala:
0 to 10 for (i <- 0 until 10) (0 until 10 by 5).start //.end .step
▶ Haskell:
[1..5] [1,1.5..5] -- 1, 1.5, 2, 2.5, ...
▶ Clojure:
(range 1 21) ; actually this produces a sequence, more on that later
www.xebia.fr / blog.xebia.fr 37
38. Types we don't have in Java (4/5)
Ranges
▶ Ruby:
myArray[1..3] (1..3).to_a (1..21).each{|n| print n}
▶ Scala:
0 to 10 for (i <- 0 until 10) (0 until 10 by 5).start //.end .step
▶ Haskell:
[1..5] [1,1.5..5] -- 1, 1.5, 2, 2.5, ...
▶ Clojure:
(range 1 21) ; actually this produces a sequence, more on that later
Tuples
› (x, y) = (1, 2) {x, y} = {1, 2}
www.xebia.fr / blog.xebia.fr 38
39. Types we don't have in Java (5/5)
Functions!
www.xebia.fr / blog.xebia.fr 39
40. Higher-Order Functions
Produces or consumes other functions
▶ Ruby:
def do_something(x, y)
z = # ...
lambda { |w| z + w }
end
▶ Haskell:
applyToArg f x = f(x)
Partial Application (~Currying)
▶ Erlang:
prod x y = x * y
double = prod 2
triple = prod 3
www.xebia.fr / blog.xebia.fr 40
42. Functional Programming Concepts
Immutability
Nil
▶ Empty list
▶ Nil.size(), count(nil)
Optional result
▶ Scala: Haskell:
map.get(aKey) match { case aValue of
case Some(x) => println(x) Just x -> ...
case None => println("Nope") Nothing -> ...
}
www.xebia.fr / blog.xebia.fr 42
43. List Comprehension
Builds a list from other list(s)
▶ Erlang:
[ {X, Y} || X <- lists:seq(1, 4), X < 3, Y <- [5, 6] ].
% [{1,5},{1,6},{2,5},{2,6}]
▶ Haskell:
[ (x, y) | x <- [1..4], x < 3, y <- [5, 6] ]
▶ Clojure:
(for [ x [1,2,3,4], y [5,6], :when (< x 3)]
(* x y))
▶ Scala:
for (x <- 1 to 2; y <- List(5, 6); if x < 3)
yield (x, y)
www.xebia.fr / blog.xebia.fr 43
44. Lazy evaluation
Delays the evaluation of an expression until its value is required
Increases performance
Allows for infinite sequences
▶ Haskell:
take 4 (dropWhile (< 34098) [0, 0.5 ..])
-- [34098.0, 34098.5, 34099.0, 34099.5]
zip (take 5 (iterate (2*) 10)) (take 5 (iterate (/2) 10))
-- [(10, 10.0), (20, 5.0), (40, 2.5), (80, 1.25), (160, 0.625)]
▶ Clojure
=> (take 5 (interpose
:and
(cycle [:x :k :e])))
(:x :and :k :and :e)
www.xebia.fr / blog.xebia.fr 44
45. Lazy evaluation
An alternative to recursion
▶ Fibonacci:
(defn fib-pair [[a b]] [b (+ a b)])
(defn fibonacci
[]
(map first
(iterate fib-pair [1 1])))
(take 10 (fibonacci))
; (1 1 2 3 5 8 13 21 34 55)
www.xebia.fr / blog.xebia.fr 45
46. Concurrency
The Problem
▶ Shared resources
▶ Interactions between threads/processes
▶ Coordination
▶ Failures
www.xebia.fr / blog.xebia.fr 46
47. Actors
An independent computational entity having a mailbox
It can send/receive messages (a-)synchronously
▶ Erlang (synchronous example):
loop() ->
receive
{From, "voiture"} ->
From ! "car",
loop();
{From, _} ->
From ! "unknown word",
loop()
end.
Service = spawn(fun loop/0).
Service ! {self(), "voiture"},
receive
Translation -> Translation
end.
www.xebia.fr / blog.xebia.fr 47
48. Actors
An independent computational entity having a mailbox
It can send/receive messages (a-)synchronously
▶ Scala (asynchronous example):
class Service extends Actor {
def act() = {
loop {
react {
case "voiture" => println("car")
case _ => println("unknown word")
}
}
}
}
val service = new Service()
service.start
service ! "voiture"
www.xebia.fr / blog.xebia.fr 48
49. Software Transactional Memory
STM
▶ Same approach as for databases (ACID)
▶ Wrap code accessing shared resources in a transaction
▶ The transaction sees values as they were when opening it
› Clojure: (def i (ref 0))
(def j (ref 0))
(dosync
(alter i inc)
(alter j dec))
– But also, in a nutshell:
Uncoordinated Coordinated
Synchronous Atom Reference (ref)
Asynchronous Agent
www.xebia.fr / blog.xebia.fr 49
50. Let it Crash!
Erlang philosophy
Cheap processes instead of threads
Monitor your processes
Make them restart on failure
Refer to the “library” example
loop() ->
process_flag(trap_exit, true),
receive
new ->
register(revolver, spawn_link(fun russian_roulette_loop/0)),
loop();
{'EXIT', From, Reason} ->
self() ! new,
loop()
end.
www.xebia.fr / blog.xebia.fr 50
52. Exercises 1. Shopping Cart
Represent a catalog in the form of a list of tuples (article, quantity, price)
Write a function that returns the price of an article when present in the catalog or
nothing/nil (depending on the language) otherwise
Using recursion, write a function that computes the total value of the catalog
Write a function that feeds a cart with items from the catalog until:
▶ either a maximum amount is reached for the cart value
▶ or the catalog is empty
Note: It might be simpler to represent the cart as a list of tuples (article, price) at first (with
the same article occuring serveral times).
Amends your function so that it also returns the catalog minus the items that are in the
cart
Using fold/reduce (depending on the language), writes a function that computes the total
value of the cart
Using a list comprehension, write a function that takes a cart and returns it with a given
tax applied to its items
Interesting candidates are: Erlang, Haskell, Clojure and Scala
www.xebia.fr / blog.xebia.fr 52
53. Exercises 2. Tic-Tac-Toe
Write a pogram that accepts a tic-tac-toe board and returns whether there is a winner
and, if it is the case, which one.
Depending on the language you choose, try to use the most different functional constructs
you can think of:
▶ list processing with functions
▶ list comprehensions
▶ pattern matching and data deconstruction
▶ ...
Should you finish the first part early, modify your program so that it tells when there is a
tie.
Interesting candidates are: Scala, Clojure, Erlang, Haskell
Alternatively, solve the problem with Prolog
www.xebia.fr / blog.xebia.fr 53
54. Exercises 3. Erlang: Chat
The aim of this exercise is to write a chat application allowing for discussing between two
terminals, based on the "translate_service", "russian_roulette" and "library" examples.
You can find template files for a server, a supervisor and a client.
The server will be in charge to log in clients and dispatch their messages. It will be built
with Erlang OTP's generic server feature.
The supervisor will be in charge to restart the server should a crash occur.
The client will spawn a process when the user requests a connection to the server, so that
this underlying process can handle messages from the server while the user use the
console process to give orders to the client.
www.xebia.fr / blog.xebia.fr 54
55. Exercises 4. Reverse Dependency Tree
Using Scala, write a program that can scan a local Maven repository for POM files and
build a reverse dependency tree for a given module.
Use actors to load and parse files concurrently, and then send pieces of dependency
model to a collecting actor.
Use Scala's XML capabilities to read POM files
www.xebia.fr / blog.xebia.fr 55
56. Exercises 5. The Sleeping Barber
A barber has one barber chair and a waiting room with a number of chairs in it.
When the barber finishes cutting a customer's hair, he dismisses the customer and then
goes to the waiting room to see if there are other customers waiting:
▶ if there are, he brings one of them back to the chair and cuts his or her hair,
▶ if there are no other customers waiting, he returns to his chair and sleeps in it.
Each customer, when he arrives, looks to see what the barber is doing:
▶ if the barber is sleeping, then he wakes him up and sits in the chair,
▶ if the barber is cutting hair, then he goes to the waiting room:
› if there is a free chair in the waiting room, he sits in it and waits his turn,
› if there is no free chair, then the customer leaves.
Write a program that print events occurring in the shop: customer arrival and departure
(and why), barber state (cutting hair, sleeping), etc...
Use the following durations: a hair cut last 100 to 500 ms, a customer enters the shop
every 1 to 450 ms. Stop sending customers after the 20th one.
www.xebia.fr / blog.xebia.fr 56