Ein Blick über den Tellerrand Funktionale Ideen in der praktischen

Werbung
Ein Blick über den Tellerrand
Funktionale Ideen in der
praktischen Programmierung
Jasper van de Ven
([email protected])
Praktische Informatik 3
Universität Bremen
Wintersemester 09/10
Motivation
You can never understand one
language until you understand at
least two.
-Roland Searle
Motivation
funktionale Programmierung in der praktischen Anwendung
einordnen
Programmiersprachen, die funktionale Konzepte unterstützen
Beispiele wo funktionale Programme mit großem Erfolg eingesetzt
werden
Ablauf
Kurze Historie der funktionalen Programmierung
Vorstellung der betrachteten Sprachen
Vorstellung der verwendeten Konzepte
Geschichtsstunde...
The future, according to some
scientists, will be exactly like the
past, only far more expensive.
-John Sladek
Geschichtsstunde...
entwickelt aus der akademischen Forschung
Lambda-Klakül
Ende 50iger Jahre → LISP
1987 → Haskell
Betrachtete Sprachen
Haskell
Erlang
Ruby
Scala
Haskell
main = putStrLn "Hello, World!"
vorgestellt 1987
Zusammenführung der
Forschung
Sprache zum
Austausch
—————————–
fac 0 = 1
fac n = n * fac (n-1)
Erlang
-mod(hello).
-export([start/0]).
start() ->
io:format("Hello, World!").
—————————–
Ericsson Computer
Science Lab
1987
Telekommunikation
-module(test).
-export([fac/1]).
fac(0) -> 1;
fac(N) -> N * fac(N-1).
Ruby
puts "Hello, world!"
—————————–
Yukihiro ’Matz’
Matsumoto
1995 (Java auch...)
Rails 2005
def fac(n)
result = 1
n.times do |i|
result *= i
end
result
end
Scala
2003 (2001
Entwicklungsbegin)
École Polytechnique
Fédérale de Lausanne
(EPFL)
Anfang 2004 → JVM
Mitte 2004 → .Net
object HelloWorld
extends Application {
println("Hello, world!")
}
—————————–
def fac(n: Int): Int = {
if(n <= 1)
1
else
n * fac(n - 1)
}
Scala
def fac(x: Int):
Int = x match {
case 0 => 1
case n => fac(n - 1) * n
}
Betrachtete Eigenschaften
Paradigmen
Typsysteme
Spezieller
funktionale Techniken in Ruby
Nebenläufigkeit in Erlang
Scala - Ein Blick in die Zukunft
Betrachtete Eigenschaften
Paradigmen
Typsysteme
Spezieller
funktionale Techniken in Ruby
Nebenläufigkeit in Erlang
Scala - Ein Blick in die Zukunft
Paradigmen der Programmierung
imperativ
deklarativ
prozedural
logisch
objektorientiert
funktional
multiparadigmatisch
Programmiersprachen unterstützen einen Stil und beschränken nicht
auf ihn
Paradigmen der Programmierung
imperativ
deklarativ
prozedural
logisch
objektorientiert
funktional
multiparadigmatisch
Programmiersprachen unterstützen einen Stil und beschränken nicht
auf ihn
Paradigmen von Haskell
rein funktional
lazy evaluation
modular
Paradigmen von Erlang
rein funktional
modular
hoch Verfügbar
Parallelität
Paradigmen von Erlang
hoch Verfügbar
Parallelität
Was heist das jetzt genau?
Ericcson: 99% Verfügbarkeit im
Jahr
A = 1+5.
B = 4+6.
C = A+B.
Paradigmen von Erlang
hoch Verfügbar
Parallelität
Was heist das jetzt genau?
Ericcson: 99% Verfügbarkeit im
Jahr
A = 1+5.
B = 4+6.
C = A+B.
Paradigmen von Erlang
hoch Verfügbar
Parallelität
Was heist das jetzt genau?
Ericcson: 99% Verfügbarkeit im
Jahr
A = 1+5.
B = 4+6.
C = A+B.
Paradigmen von Ruby
multiparadigmatisch
objektorientiert (prozedural, funktional)
modular
Metaprogrammierung
Paradigmen von Scala
multiparadigmatisch
objektorientiert, funktional, imperativ
direkte Anbindung an Java
Typsysteme
[A type system is a] tractable
syntactic method for proving the
absence of certain program
behaviors by classifying phrases
according to the kinds of values they
compute.
-Benjamin C. Pierce
Haskell und Erlang
Haskell
statisch
stark
Typinferenz
Erlang
dynamisch
stark
Haskell und Erlang
Haskell
statisch
stark
Typinferenz
Erlang
dynamisch
stark
Ruby
Duck-Typing
class Ente
class Kuh
def beschreibung
def beschreibung
"Eine graue Ente"
"Eine dicke Kuh"
end
end
def sprechen
def sprechen
"Quak!"
"Muuuh!"
end
end
end
end
def lass_sprechen tier
puts tier.beschreibung+ " macht "+tier.sprechen
end
lass_sprechen Ente.new
lass_sprechen Kuh.new
Ruby
Duck-Typing
class Ente
class Kuh
def beschreibung
def beschreibung
"Eine graue Ente"
"Eine dicke Kuh"
end
end
def sprechen
def sprechen
"Quak!"
"Muuuh!"
end
end
end
end
def lass_sprechen tier
puts tier.beschreibung+ " macht "+tier.sprechen
end
lass_sprechen Ente.new
lass_sprechen Kuh.new
Scala
statisch
stark
Typinferenz
object InferenceTest1
extends Application {
val x = 1 + 2 * 3
val y = x.toString()
def succ(x: Int) = x + 1
}
Scala
statisch
stark
Typinferenz
object InferenceTest1
extends Application {
val x = 1 + 2 * 3
val y = x.toString()
def succ(x: Int) = x + 1
}
Scala
object InferenceTest2 {
def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1)
}
———————–
case class MyPair[A, B](x: A, y: B);
object InferenceTest3 extends Application {
def id[T](x: T) = x
val p = new MyPair(1, "scala")
val q = id(1)
}
val x: MyPair[Int, String] =
new MyPair[Int, String](1, "scala")
val y: Int = id[Int](1)
Scala
object InferenceTest2 {
def fac(n: Int) = if (n == 0) 1 else n * fac(n - 1)
}
———————–
case class MyPair[A, B](x: A, y: B);
object InferenceTest3 extends Application {
def id[T](x: T) = x
val p = new MyPair(1, "scala")
val q = id(1)
}
val x: MyPair[Int, String] =
new MyPair[Int, String](1, "scala")
val y: Int = id[Int](1)
Scala
object InferenceTest4 {
var obj = null
obj = new Object()
}
Funktionale Konzepte in Ruby
Funktionen höherer Ordnung
Anonyme Funktionen
Proc Objekte
Code Blocks
Funktionale Konzepte in Ruby
Funktionen höherer Ordnung
Anonyme Funktionen
Proc Objekte
Code Blocks
Proc Objekte
Proc objects are blocks of code that
have been bound to a set of local
variables. Once bound, the code may
be called in different contexts and still
access those variables.
-Ruby Dokumentation
Proc Objekte
def gen_times(factor)
return Proc.new {|n| n*factor }
end
times3 = gen_times(3)
times5 = gen_times(5)
times3.call(12)
times5.call(5)
times3.call(times5.call(4))
#=> 36
#=> 25
#=> 60
Proc Objekte
def foo (a, b)
a.call(b)
end
putser = Proc.new {|x| puts x}
foo(putser, 34)
————————————
putser = lambda {|x| puts x}
Proc Objekte
def foo (a, b)
a.call(b)
end
putser = Proc.new {|x| puts x}
foo(putser, 34)
————————————
putser = lambda {|x| puts x}
Code Blocks
# a naked block can’t live in Ruby
# this is a compilation error !
{puts "hello"}
———————–
# now it’s alive, having been converted
# to a Proc !
pr = lambda {puts "hello"}
pr.call
Code Blocks
# a naked block can’t live in Ruby
# this is a compilation error !
{puts "hello"}
———————–
# now it’s alive, having been converted
# to a Proc !
pr = lambda {puts "hello"}
pr.call
Code Blocks
10.times do |i|
print "#{i} "
end
numbers = [1, 2, 5, 6, 9, 21]
numbers.each do |x|
puts "#{x} is " + (x >= 3 ? "many" : "few")
end
squares = numbers.map {|x| x * x}
Code Blocks
def do_twice(&block)
yield
yield
end
do_twice {puts "Hola"}
Nebenläufigkeit in Erlang
Prozessstruktur
Message-passing
Nebenläufigkeit in Erlang
-module(ping_pong).
-export([ping/0, pong/0]).
ping() ->
Pong = spawn(ping_pong, pong, []),
Pong ! {self(), ping},
receive
pong ->
pong
end.
pong() ->
receive
{Ping, ping} ->
Ping ! pong
end.
Scala - Funktionaler Zucker und Nebenläufigkeit
Actor-Designpattern
Funktionen höherer Ordnung
Anonyme Funktionen
Actor-Pattern
import scala.actors.Actor
import scala.actors.Actor._
val fussyActor = actor {
loop {
receive {
case s: String =>
println("I got a String: " + s)
case i: Int =>
println("I got an Int: " + i.toString)
case _ =>
println("I have no idea what I just got.")
}
}
}
Actor-Patterm
fussyActor ! "hi there"
fussyActor ! 23
fussyActor ! 3.33
Funktionen höherer Ordnung
def apply(f: Int => String, v: Int) = f(v)
———————–
class Decorator(left: String, right: String) {
def layout[A](x: A) = left + x.toString() + right
}
object FunTest extends Application {
def apply(f: Int => String, v: Int) = f(v)
val decorator = new Decorator("[", "]")
println(apply(decorator.layout, 7))
}
Funktionen höherer Ordnung
def apply(f: Int => String, v: Int) = f(v)
———————–
class Decorator(left: String, right: String) {
def layout[A](x: A) = left + x.toString() + right
}
object FunTest extends Application {
def apply(f: Int => String, v: Int) = f(v)
val decorator = new Decorator("[", "]")
println(apply(decorator.layout, 7))
}
Anonyme Funktionen
new Function1[Int, Int] {
def apply(x: Int): Int = x + 1
}
(x: Int, y: Int) => "(" + x + ", " + y + ")"
() => { System.getProperty("user.dir") }
Anonyme Funktionen
new Function1[Int, Int] {
def apply(x: Int): Int = x + 1
}
(x: Int, y: Int) => "(" + x + ", " + y + ")"
() => { System.getProperty("user.dir") }
Closures
object TargetTest1 extends Application {
def whileLoop(cond: => Boolean)
(body: => Unit): Unit =
if (cond) {
body
whileLoop(cond)(body)
}
var i = 10
whileLoop (i > 0) {
println(i)
i -= 1
}
}
Einsatzgebiete und bekannte Projekte
Haskell → akademische Welt
Erlang → Telekommunikationssysteme (Ericsson)
Ruby → Ruby on Rails (Web 2.0)
Scala → Twitter (Web 2.0) aber auch z.B. durch französischem
Energie Unternehmen Électricité de France (EDF)
Fazit
Use the right tools for the job...
-an old saying
Zum Abschluss noch zwei Kleinigkeiten...
Fazit
Use the right tools for the job...
-an old saying
Zum Abschluss noch zwei Kleinigkeiten...
Remember...
1
1
http://xkcd.com/519/
In Gedenken an Klaus’ Katzen-Presentationen...
2
Ich hoffe, dass hab ich...
2
http://catsonthecounter.blogspot.com/2009/09/im-not-lazyim-sickyeahthat.html
Herunterladen