Methoden höherer Ordnung L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 1 Das Grundprinzip Funktionen werden in der funktionalen Programmierung wie alle anderen Daten behandelt. Daher können Funktionen sowohl Argumente, als auch Ergebnisse von Funktionen sein. In Haskell: accu f (x:[]) = x accu f (x:xs) = f x (accu f xs) accu angewandt auf f und eine Liste mit nur dem Element x accu angewandt auf f und eine Liste mit dem Kopf x und dem Rest xs L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 2 Wie ist das in Java? In Java werden Methoden anders als andere Daten behandelt. Wir lernen eine Möglichkeit kennen, um Methoden zu definieren, die indirekt andere Methoden als Argumente verarbeiten können oder andere Methoden als Ergebnis liefern können. L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 3 Erst einmal was Anderes Dog[] dogs ={ new Dog("Snoopy", 42, Unit.CM), new Dog("Bello", 23, Unit.CM), new Dog("Lassie", 23, Unit.CM) }; Arrays.sort(dogs); Was passiert? ClassCastException nach Comparable L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 4 Vergleichbare Hunde class Dog implements Comparable<Dog>{ ... public int compareTo(Dog other) { if(size<other.size) return -1; else if(size>other.size) return 1; else return name.compareTo(other.name); } } Jetzt klappt es! Nach welchen Kriterien wird sortiert? L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 5 Eine flexiblere Lösung sort(T[] a, Comparator<? super T> c) public interface Comparator<Dog>{ int compare(Dog dog1, Dog dog2); } Wie funktioniert das? L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 6 Eine flexiblere Lösung class DogComparator implements Comparator<Dog>{ public int compare(Dog dog1, Dog dog2){ if(dog1.equals(dog2)){ return 0; } int result = dog1.getName().compareTo(dog2.getName()); if(result!=0){ return result; } return dog1.getSize()<dog2.getSize() ? -1 : 1; } } Arrays.sort(dogs, new DogComparator()); Nach welchen Kriterien wird hier sortiert? L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 7 Alles auf Einmal Arrays.sort(dogs, new Comparator<Dog>(){ public int compare(Dog dog1, Dog dog2) { if(dog1.equals(dog2)){return 0;} final int result = dog1.getName().compareTo(dog2.getName()); if(result!=0){return result;} return dog1.getSize()<dogs.getSize() ? -1 : 1; } } ); Anonyme innere Klasse, die Comparator<Dog> implementiert. L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 8 Entwurfsmuster Objektorientierte Programmierung erfordert einige Erfahrung Viele Probleme treten immer wieder auf Typische Problemstellungen werden zusammen mit einer Standardlösung zu einem Entwurfsmuster zusammengefasst. Es gibt einen anerkannten Katalog von Mustern. Der Katalog bietet nicht nur Lösungen für Standardprobleme an, sondern bietet auch eine Terminologie, die erfahrene Programmierer kennen. L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 9 Das Strategiemuster „Definiere eine Familie von Algorithmen, kapsele jeden einzelnen und mache sie austauschbar. Das Strategiemuster ermöglicht es, den Algorithmus unabhängig ̈ von ihn nutzenden Klienten zu variieren.“ Hier: Algorithmus = compareTo-Methode Kapsel = Comparator Klient = sort L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 10 Strategiemuster - Noch ein Beispiel Thread t = new Thread( new Runnable(){ public void run() { while(true) System.out.println(new Date()); } } ); t.start(); L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 11 Das Strategiemuster und Funktionale Auch wenn Java keine Methoden höherer Ordnung bietet: Mit Hilfe des Strategiemuster können wir Methoden höherer Ordnung nachbilden. L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 12 Einfache Codes Der Cäsar-Code HELLO IFMMP Jeder Buchstabe wir durch seinen alphabetischen Nachfolger ersetzt. Erweiterung: Nicht den unmittelbaren Nachfolger wählen, sondern den jeweils k-ten Nachfolger L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 13 Funktionen als Objekte erster Klasse interface Function<T> { T f(T v); } class Coder implements Function<Character>{ private int offset; public Coder(int offset){this.offset = offset%26;} public Character f(Character letter) { if(letter>'Z' || letter<'A'){ throw new IllegalArgumentException(letter.toString()); } return (char)('A'+(letter-'A'+offset)%26); } } Cäsar entspricht Coder(1) L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 14 Eine Methode höherer Ordnung String transformer(Function<Character> coder, String text){ final StringBuilder result = new StringBuilder(text.length()); for(int i=0; i<text.length(); i++){ final Character coded = coder.f(text.charAt(i)); result.append(coded); } return result.toString(); } Der zu verschlüsselnde Text entspricht dem zweiten Parameter, Die zeichenweise Abbildung entspricht dem ersten Parameter L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 15 Beispiel zu Anwendung transformer(new Coder(23), "HALLO") Liefert EBIIL transformer(new Coder(-23), "EBIIL") Liefert HALLO L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 16 Methode mit einer Methode als Ergebnis = Methode höherer Ordnung Function<String> transformer(final Function<Character> coder){ return new Function<String>(){ public String f(String text) { return transformer(coder, text); } }; } L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 17 Beispiel Function<String> encoder = transformer( new Coder(23) ); Function<String> decoder = transformer( new Coder(-23) ); System.out.println(decoder.f(encoder.f("HELLO"))); L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 18 Alles klar? Eine Funktion höherer Ordnung ist eine Funktion, der man Funktionen als Argument übergeben ̈ kann oder deren Ergebnis eine Funktion ist. erlaubt es, Funktionen zu verallgemeinern, da Teile ihrer Funktionalität parametrisiert werden können. kann in jeder funktionalen Programmiersprache benutzt werden. gibt es in Java nicht. In Java kann man ersatzweise mit dem Strategiemuster arbeiten. L. Piepmeyer: Funktionale Programmierung - Funktionen höherer Ordnung 19