Algorithmen und Datenstrukturen II · Imperative vs. funktionale Programmierung Vergleich zwischen...
Transcript of Algorithmen und Datenstrukturen II · Imperative vs. funktionale Programmierung Vergleich zwischen...
Algorithmen und Datenstrukturen II
Peter Steffen
AG Praktische InformatikTechnische FakultatUniversitat Bielefeld
Vorlesung Sommer 2009
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Teil I
Ubergang von funktionaler zu OOP
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Imperative vs. funktionale Programmierung
Plakativ lassen sich folgende Aussagen treffen:
funktional: Berechnung von Werten von Ausdruckenimperativ: Berechnung des Kontrollflusses
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Beispiele zur Unterscheidung: Java vs. Haskell (I)
Beispiel (Berechnung des Betrages einer ganzen Zahl n)
public static int abs(int n) {if (n >= 0)return n;
elsereturn -n;
}
> abs’ :: (Ord a, Num a) => a -> a> abs’ n | n >= 0 = n> | otherwise = -n
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Beispiele zur Unterscheidung: Java vs. Haskell (II)
Beispiel (Berechnung von sum(n) =n∑
i=1
i2)
public static int sum(int n) {
int s = 0;
for(int i=1; i<=n; i++)
s = s + i * i;
return s;
}
> sum’ :: (Enum a, Num a) => a -> a
> sum’ n = foldl g 0 [1..n]
> where g x y = x + y * y
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Beispiele zur Unterscheidung: Java vs. Haskell (II)
Beispiel (Berechnung vonnextSquare(n) = min{q | q > n, q = s2, s ∈ N})
public static int nextSquare(int n) {
int i = 1;
int q = 1;
while (q <= n) {
i++;
q = i*i;
}
return q;
}
> nextSquare’ :: (Num a, Enum a) => a -> a
> nextSquare’ n = (head.dropWhile (<=n).map (^2)) [1..]
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Entsprechungen/Unterschiede
funktional imperativ
Liste vonZwischenergebnissen(anonym)
Rekursionsschemata(foldl, map)
abstrahiert vonZwischenergebnissen
Speicheraufwandig
Listen spielen eine zentraleRolle
Wertabfolgen in Behaltern(benannt)
spezielle Anweisungen(while, for)
Behalter werdenweiterbenutzt
Speicherokonomisch
Listen sind ein Datentypwie viele andere
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Beispiel (Listen in Java)
public class Node {
protected int element;
protected Node next;
public Node(int val, Node node) {
element = val;
next = node;
}
public int element() {
return element;
}
public Node next() {
return next;
}
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Knoten zu Listen verknupfen
[1,2] =1s �- 2s �
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Die Konstruktoren von IntList
Beispiel (Konstruktur IntList)
public class IntList {private Node first = null;
public IntList() { }
public IntList(Node first) {this.first = first;
}}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
public IntList ()
first�public IntList (Node first)
first�- 1r ��- 2r ��- · · ·r ��- nr ��Beispiel (Methode emtpy testet, ob Liste leer ist)
public boolean empty() {return first == null;
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Die Methode cons
Beispiel
/** cons builds up lists. Returns a new reference to the list
cons(val,xs), does not change xs. In order to emphasize that cons
doesn’t change the list it acts upon, it is declared static. */
public static IntList cons(int val, IntList xs) {
Node n = new Node(val, xs.first);
return new IntList(n);
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Cons-Beispiel
cons(x,xs) wobei in (a) xs leer ist und in (b) xs der Liste [2,3]entspricht.
(a)
(b)
xs.first� return value�- xr ��xs.first�
xs.first�- 2r ��- 3r ��return value�- xr ��-
xs.first�- 2r ��- 3r ��
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Die Methoden head und tail
Die Funktionen head und tail sind in Haskell folgendermaßendefiniert:
head (x:xs) = x tail (x:xs) = xs
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Beispiel
/** Returns the first element of a list. Returns -1 and prints an
error message if the list is empty; does not change the list. */
public int head() {
if (empty()) {
System.out.println("Error at method head(): Empty List");
return -1; // an exception would be better
}
return first.element();
}
/** Returns a new reference to the list obtained by removing the
first element. Returns null and prints an error message if the
list is empty; does not change the list. */
public IntList tail() {
if (empty()) {
System.out.println("Error at method tail(): Empty List");
return null; // an exception would be better
}
return new IntList(first.next());
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Die Methode append
Die Definition von append lautet in Haskell:
append [] ys = ysappend (x:xs) ys = x:append xs ys
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Append rekursiv
Beispiel (append rekursiv)
/** Returns a new reference to the list obtained by concatenation
of xs and ys; does not change the lists. In order to
emphasize this, it is declared static. */
public static IntList append(IntList xs,IntList ys) {
if (xs.empty())
return ys;
else
return cons(xs.head(),append(xs.tail(),ys));
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
... und nicht-rekursiv
Beispiel (append nicht-rekursiv)
private static IntList append2(IntList xs,IntList ys) {
Node tmp;
if (xs.empty())
return ys;
else {
for(tmp=xs.first; tmp.next!=null; tmp=tmp.next)
; // Find last node
tmp.next = ys.first;
return xs;
}
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Append-Beispiel
xs.first�- 1q ��- 2q �� ys.first�- 3q ��- 4q ��- 5q ��zs = append(xs,ys) bzw. zs = append2(xs,ys)
��
�
@@
@R
append (rekursiv)(nicht desktruktive Variante)
append2 (nicht rekursiv)(desktruktive Variante)
xs.first�- 1q ��- 2q ��zs.first�- 1q ��- 2q ��-
ys.first�- 3q ��- 4q ��- 5q ��xs.first�-zs.first
�- 1q ��- 2q ��-ys.first�- 3q ��- 4q ��- 5q ��
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Seiteneffekte!
Das Verhalten von append2 ist destruktiv, denn beim Verkettenvon xs und ys wird xs zerstort (oder milder ausgedruckt,verandert). Diesen Seiteneffekt muss man bei jeder Anwendungvon append2 berucksichtigen! Aber auch die erste Version birgteine Gefahr: Wenn nach zs = append(xs,ys) die Liste ysverandert wird, verandert sich damit auch zs.
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Sonderfall xs = ys
xs.first�- 1q ��- 2q ��zs = append(xs,xs) bzw. zs = append2(xs,xs)
���
@@@R
append append2
zs.first�- 1q ��- 2q ��-xs.first�- 1q ��- 2q �� xs.first�-
zs.first
�- 1q ��- 2q � 6
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Vergleich zwischen Haskell und Java
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Parametrischer Typpolymorphismus
Die Haskell-Funktion swap ist definiert durch:
Definition
swap :: (a,b) -> (b,a)swap (x,y) = (y,x)
Beispielsweise ist (1,"a") das Ergebnis von swap("a",1).
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Um diese Funktion in Java zu implementieren, benutzen wir den Typ Object.
Beispiel
public class Pair {
protected Object x;
protected Object y;
public Pair(Object x, Object y) {
this.x = x;
this.y = y;
}
public void swap() {
Object tmp = x;
x = y;
y = tmp;
}
public static void main(String[] args) {
Pair p = new Pair("a",new Integer(1));
p.swap();
System.out.println(((Integer)(p.x)).intValue()+(String)p.y);
}
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Da elementare Daten keine Objekte sind, mussen sie in Objekteverwandelt werden. Dies geschieht mit Hilfe der Hullenklassen –elementare Daten werden durch einen Hullenklassenkonstruktor“eingehullt”und damit zu Objekten.
Object��
��� ?
HHHHj
Boolean Char NumberPPPPPPq
@@R
��
������)LongIntegerDoubleFloat
Abbildung: Klassenhierarchie der Hullenklassen
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
IntPair
Beispiel
public class IntPair {
protected int x;
protected int y;
public IntPair(int x, int y) {
this.x = x;
this.y = y;
}
public void swap() {
int tmp = x;
x = y;
y = tmp;
}
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Generic Types
Seit Java 5 konnen Klassen mit Typparametern definiertwerden.
Solche Klassen werden Generische Klassen oderParametrisierte Klassen genannt.
Der Typparameter wird in ’<>’ nach dem Klassennamenangegeben.
Generische Klassen werden wie andere Klassen auch benutzt,jedoch muss bei der Instanziierung der Typ angegeben werden
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Beispiel (Generic Types)
class Pair<E> {
protected E x;
protected E y;
public Pair(E x, E y) {
this.x = x;
this.y = y;
}
public void swap() {
E tmp = x;
x = y;
y = tmp;
}
public static void main(String[] args) {
Pair<Integer> intPair = new Pair<Integer>(1,2);
Pair<String> charPair = new Pair<String>("a","b");
intPair.swap();
charPair.swap();
System.out.println(intPair.x + "," + intPair.y);
System.out.println(charPair.x + "," + charPair.y);
}
}Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Funktionen hoherer Ordnung
In Haskell gibt es keinen Unterschied zwischen Funktionen undDaten: Funktionen konnen Argumente anderer Funktionen sein,Funktionen konnen Funktionen als Wert liefern etc. In Java sindFunktionen (Methoden) Bestandteil von Objekten. Da FunktionenObjekte als Argumente oder Ruckgabewert haben konnen,unterstutzt Java insofern Funktionen hoherer Ordnung.
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Klassen, Objekte und Vererbung
in Java kein Problem (objektorientierte Programmiersprache);
Haskell-Klassen definieren abstrakte Methoden, jedoch keineObjekte. Eine Instanz einer Klasse muss diese abstraktenMethoden implementieren (d.h. eine eigene Definitionangeben). Insofern entspricht eine Haskell-Klasse grobgesprochen einer abstrakten Klasse in Java, die nur abstrakteMethoden enthalt (genauer einer Schnittstelle).
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Keine Entsprechung gibt es z.B.
in Java fur die unendlichen Datenstrukturen in Haskell
in Haskell fur die von Java unterstutzte Nebenlaufigkeit
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Algebraische Datentypen und Pattern Matching (I)
Pattern Matching kann nach einer Idee von Odersky & Wadler(1997) auf sehr elegante Art und Weise simuliert werden. Wirdemonstrieren dies an Hand der append-Funktion auf Listen.
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Algebraische Datentypen und Pattern Matching (II)
Beispiel
public class List {
protected static final int NIL_TAG = 0;
protected static final int CONS_TAG = 1;
protected int tag;
public List append(List ys) {
switch (this.tag) {
case NIL_TAG:
return ys;
case CONS_TAG:
char x = ((Cons)this).head;
List xs = ((Cons)this).tail;
return new Cons(x, xs.append(ys));
default:
return new Nil(); //an exception would be better
}
}
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
Algebraische Datentypen und Pattern Matching (III)
Beispiel
public class Cons extends List {
protected char head;
protected List tail;
public Cons(char head, List tail) {
this.tag = CONS_TAG;
this.head = head;
this.tail = tail;
}
}
public class Nil extends List {
public Nil() {
this.tag = NIL_TAG;
}
}
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009
Imperative vs. funktionale Programmierung Vergleich zwischen Haskell und Java
K. Arnold, J. Gosling: JavaTM - Die Programmiersprache.Addison-Wesley, 1996.
T.H. Cormen, C.E. Leierson, R.L. Rivest: Introduction toAlgorithms. MIT Press, 1990.
D. Flanagan: Java in a Nutshell. O’Reilly & Associates Inc.,1996.
F. Jobst: Programmieren in Java. Hanser Verlag, 1996.
H. Klaeren: Vom Problem zum Programm. 2.Auflage,B.G. Teubner Verlag, 1991.
K. Echtle, M. Goedicke: Lehrbuch der Programmierung mitJava. dpunkt-Verlag, 2000.
Peter Steffen Universitat Bielefeld
A&D II, Vorlesung 2009