Currying und partielle Funktionsanwendung
Funktionen in Ein-Parameter-Funktionen umwandeln
In den vorangegangen Kapiteln haben wir ausgiebig die unterschiedlichsten Funktionen implementiert. Einige davon haben nur ein Übergabedatum erhalten, andere mehrere. Tatsächlich lässt sich aber auch jede Funktion, die mehr als ein Übergabedatum erwartet, in eine Kette von Funktionen transformieren, bei der jede einzelne Funktion genau ein Übergabedatum entgegennimmt und anschließend eine weitere Funktion zurückgibt. Diesen Prozess bezeichnet man als Currying.Aufgabe 1: Rabattberechnungen
Die unten stehende Funktion rabatt
berechnet für die
Übergabe eines Prozentwerts und eines Ausgangspreises den Preis nach Abzug
des Rabatts.
(: rabatt (real real -> real))
(define rabatt
(lambda (prozent preis)
(* preis (- 1 (/ prozent 100)))))
Eine weitere Möglichkeit, die Funktion zu strukturieren, ist die folgenden:
(: rabatt-curry (real -> (real -> real)))
(define rabatt-curry
(lambda (prozent)
(lambda (preis)
(* preis (- 1 (/ prozent 100))))))
(a) Führe die unten stehenden Ausdrücke in der REPL aus. Vergleiche dabei den Aufbau der Ausdrücke und die berechneten Ergebnisse.
> (rabatt 10 200)
> ((rabatt-curry 10) 200)
(b) Beantworte die folgenden Fragen:
- Was gibt der Funktionsaufruf
(rabatt-curry 10)
zurück? - Handelt es sich bei der Funktion
rabatt
um eine Funktion höherer Ordnung? Begründe deine Meinung. - Handelt es sich bei der Funktion
rabatt-curry
um eine Funktion höherer Ordnung? Begründe deine Meinung. - Warum besitzt die Funktion
rabatt-curry
zwei->
in der Signatur, die Funktionrabatt
jedoch nur eine?
(c) Erkläre, warum der unten stehende Ausdruck (rabatt-10)
dasselbe Ergebnis liefert, wie
die Ausdrücke in Aufgabenteil (a).
(define rabatt-10 (rabatt-curry 10))
(rabatt-10 200)
(d) Die Firma Racket-Clothing bietet für einzelne Produkte immer wieder Rabattaktionen an. Dabei sind die Produkte immer entweder um 25 %, 50 % oder 75 % reduziert. Definiere analog zu Aufgabenteil (c), drei geeignete Funktionen zur Berechnung der reduzierten Preise für die jeweiligen Prozentsätze.
Aufgabe 2: Feste Listenfilter
Die unten stehende Funktion gibt für ein übergebenes x
und eine übergebene Liste lis
eine Liste zurück, die alle Elemente von lis
enthält, die
größer als x
sind.
(: groesser-x (real (list-of real) -> (list-of real)))
(define groesser-x
(lambda (x lis)
(filter (lambda (elem) (< x elem)) lis)
))
(a) Wandle die Funktion groesser-x
durch Currying in eine Funktion groesser-x-curry
um.
(b) Definiere mithilfe deiner in Aufgabenteil (a) umgesetzten Funktion die nachfolgenden Funktionen und teste diese.
-
groesser-10
filtert auf alle Elemente größer 10.
-
filter-positiv
filtert auf alle positiven Elemente.
-
filter-bestanden
filtert für eine Liste mit verschiedenen Notenpunkten im Bereich 0 bis 15 alle Noten, die als bestanden gelten.