Ein Blick über den Tellerrand Funktionale Ideen in der ... fileMotivation funktionale...

58
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

Transcript of Ein Blick über den Tellerrand Funktionale Ideen in der ... fileMotivation funktionale...

Ein Blick über den TellerrandFunktionale Ideen in der

praktischen Programmierung

Jasper van de Ven([email protected])

Praktische Informatik 3Universität Bremen

Wintersemester 09/10

Motivation

You can never understand onelanguage until you understand at

least two.-Roland Searle

Motivation

funktionale Programmierung in der praktischen AnwendungeinordnenProgrammiersprachen, die funktionale Konzepte unterstützenBeispiele wo funktionale Programme mit großem Erfolg eingesetztwerden

Ablauf

Kurze Historie der funktionalen ProgrammierungVorstellung der betrachteten SprachenVorstellung der verwendeten Konzepte

Geschichtsstunde...

The future, according to somescientists, will be exactly like thepast, only far more expensive.

-John Sladek

Geschichtsstunde...

entwickelt aus der akademischen ForschungLambda-KlakülEnde 50iger Jahre → LISP1987 → Haskell

Betrachtete Sprachen

HaskellErlangRubyScala

Haskell

vorgestellt 1987Zusammenführung derForschungSprache zumAustausch

main = putStrLn "Hello, World!"

—————————–

fac 0 = 1fac n = n * fac (n-1)

Erlang

Ericsson ComputerScience Lab1987Telekommunikation

-mod(hello).-export([start/0]).

start() ->io:format("Hello, World!").

—————————–

-module(test).-export([fac/1]).

fac(0) -> 1;fac(N) -> N * fac(N-1).

Ruby

Yukihiro ’Matz’Matsumoto1995 (Java auch...)Rails 2005

puts "Hello, world!"

—————————–

def fac(n)result = 1n.times do |i|

result *= iendresult

end

Scala

2003 (2001Entwicklungsbegin)École PolytechniqueFédérale de Lausanne(EPFL)Anfang 2004 → JVMMitte 2004 → .Net

object HelloWorldextends Application {

println("Hello, world!")}

—————————–

def fac(n: Int): Int = {if(n <= 1)

1else

n * fac(n - 1)}

Scala

def fac(x: Int):Int = x match {

case 0 => 1case n => fac(n - 1) * n

}

Betrachtete Eigenschaften

ParadigmenTypsysteme

Speziellerfunktionale Techniken in RubyNebenläufigkeit in ErlangScala - Ein Blick in die Zukunft

Betrachtete Eigenschaften

ParadigmenTypsysteme

Speziellerfunktionale Techniken in RubyNebenläufigkeit in ErlangScala - Ein Blick in die Zukunft

Paradigmen der Programmierung

imperativprozeduralobjektorientiert

deklarativlogischfunktional

multiparadigmatisch

Programmiersprachen unterstützen einen Stil und beschränken nichtauf ihn

Paradigmen der Programmierung

imperativprozeduralobjektorientiert

deklarativlogischfunktional

multiparadigmatisch

Programmiersprachen unterstützen einen Stil und beschränken nichtauf ihn

Paradigmen von Haskell

rein funktionallazy evaluationmodular

Paradigmen von Erlang

rein funktionalmodularhoch VerfügbarParallelität

Paradigmen von Erlang

hoch Verfügbar Parallelität

Was heist das jetzt genau?

Ericcson: 99% Verfügbarkeit imJahr

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 imJahr

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 imJahr

A = 1+5.B = 4+6.C = A+B.

Paradigmen von Ruby

multiparadigmatischobjektorientiert (prozedural, funktional)modularMetaprogrammierung

Paradigmen von Scala

multiparadigmatischobjektorientiert, funktional, imperativdirekte Anbindung an Java

Typsysteme

[A type system is a] tractablesyntactic method for proving the

absence of certain programbehaviors by classifying phrases

according to the kinds of values theycompute.

-Benjamin C. Pierce

Haskell und Erlang

HaskellstatischstarkTypinferenz

Erlangdynamischstark

Haskell und Erlang

HaskellstatischstarkTypinferenz

Erlangdynamischstark

Ruby

Duck-Typing

class Entedef beschreibung"Eine graue Ente"

enddef sprechen"Quak!"

endend

class Kuhdef beschreibung

"Eine dicke Kuh"enddef sprechen

"Muuuh!"end

enddef lass_sprechen tierputs tier.beschreibung+ " macht "+tier.sprechen

end

lass_sprechen Ente.newlass_sprechen Kuh.new

Ruby

Duck-Typing

class Entedef beschreibung"Eine graue Ente"

enddef sprechen"Quak!"

endend

class Kuhdef beschreibung

"Eine dicke Kuh"enddef sprechen

"Muuuh!"end

enddef lass_sprechen tierputs tier.beschreibung+ " macht "+tier.sprechen

end

lass_sprechen Ente.newlass_sprechen Kuh.new

Scala

statischstarkTypinferenz

object InferenceTest1extends Application {

val x = 1 + 2 * 3val y = x.toString()def succ(x: Int) = x + 1

}

Scala

statischstarkTypinferenz

object InferenceTest1extends Application {

val x = 1 + 2 * 3val 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) = xval 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) = xval 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 = nullobj = new Object()

}

Funktionale Konzepte in Ruby

Funktionen höherer OrdnungAnonyme Funktionen

Proc ObjekteCode Blocks

Funktionale Konzepte in Ruby

Funktionen höherer OrdnungAnonyme Funktionen

Proc ObjekteCode Blocks

Proc Objekte

Proc objects are blocks of code thathave been bound to a set of local

variables. Once bound, the code maybe 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) #=> 36times5.call(5) #=> 25times3.call(times5.call(4)) #=> 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)yieldyield

end

do_twice {puts "Hola"}

Nebenläufigkeit in Erlang

ProzessstrukturMessage-passing

Nebenläufigkeit in Erlang

-module(ping_pong).-export([ping/0, pong/0]).

ping() ->Pong = spawn(ping_pong, pong, []),Pong ! {self(), ping},receivepong ->pong

end.

pong() ->receive{Ping, ping} ->Ping ! pong

end.

Scala - Funktionaler Zucker und Nebenläufigkeit

Actor-DesignpatternFunktionen höherer OrdnungAnonyme Funktionen

Actor-Pattern

import scala.actors.Actorimport 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 ! 23fussyActor ! 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) {bodywhileLoop(cond)(body)

}var i = 10whileLoop (i > 0) {println(i)i -= 1

}}

Einsatzgebiete und bekannte Projekte

Haskell → akademische WeltErlang → Telekommunikationssysteme (Ericsson)Ruby → Ruby on Rails (Web 2.0)Scala → Twitter (Web 2.0) aber auch z.B. durch französischemEnergie 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

1http://xkcd.com/519/

In Gedenken an Klaus’ Katzen-Presentationen...

2

Ich hoffe, dass hab ich...2http://catsonthecounter.blogspot.com/2009/09/im-not-lazyim-sickyeahthat.html