Prozeduren höherer Ordnung (I)

Aus ProgrammingWiki
Archivierte Version vom 2010-10-11T08:24:40+00:00. Aktuelle Version

Inhaltsverzeichnis

Prozeduren nehmen Prozeduren entgegen

Wir betrachten folgende zweistellige Prozeduren:

<eval id="4c83712e863bd">(add2 3 4)</eval>

<eval id="4c83712e864f8">(sub2 3 4)</eval>

<eval id="4c83712e86697">(mult2 3 4)</eval>

<eval id="4c83712e867d4">(div2 3 4)</eval>

Zweistellige Prozeduren höherer Ordnung

Die Prozeduren unterscheiden sich nur durch die Verwendung des Operators. Wir entwickeln deshalb eine (zunächst) zweistellige Universalprozedur:

<eval id="4b1107f5e2eb2">(verarbeiten2 + 3 4)</eval>

Die Prozedur verarbeiten2 nimmt neben den beiden Operanden x und y einen Operator bzw. eine Prozedur entgegen.
Sie ist damit eine Prozedur höherer Ordnung.
Prozeduren höherer Ordnung nehmen Prozeduren als Argumente entgegen oder geben Prozeduren als Funktionswerte zurück.

Hoeher1.GIF

Gegeben sei die zweistellige Prozedur:

Wir testen unsere Universalprozedur: <eval id="4b1107f5e3e4e"> (verarbeiten2 maximum2 3 4) </eval>

Variabelstellige Prozeduren höherer Ordnung

Es ist bekannt, dass die Standard-Prozeduren +, -, * und / variabelstellige Prozeduren sind, die eine beliebige Anzahl von Operanden entgegen nehmen können, mindestens aber einen Operanden benötigen.
Wir generalisieren deshalb unsere Universalprozedur zur variabelstelligen Prozedur verarbeiten:

<eval id="4b1107f5e4def">(verarbeiten + 1 2 3 4 5 6 7 8 9 10)</eval>

Aus der Syntax der Prozedurdefinition ist erkennbar, dass die Argumente op und x zwingend erforderlich sind, während alle weiteren Parameter zu einer Liste zusammengefasst werden. Diese Liste kann durchaus leer sein.

Hinweis: Die Nacheinanderausführung von cons und eval kann auch mit der Prozedur apply zusammengefasst werden:

(define verarbeiten
  (lambda (op x . y)
    (apply op (cons x y))))

Nun können wir auch die Maximum-Prozedur zu einer variabelstelligen Prozedur erweitern:

Ergänzen Sie die Hilfsprozedur max-help, mit der aus dem Argument x sowie einer weiteren Zahlenliste ls das Maximim zurückgegeben werden soll.

<eval id="4b1107f5e5d94">(verarbeiten maximum 2 3 6 3 6 1 4)</eval>

Die Prozedur map

Testen Sie die Standard-Prozedur map an verschiedenen Beispielen:

<eval id="4b1107f5e6d30">(map sqr '(1 2 3 4 5 6 7 8 9 10))</eval>

Beschreiben Sie die Signatur dieser Prozedur.
Begründen Sie, warum map eine Prozedur höherer Ordnung ist.
Bilden Sie nun diese Standard-Prozedur mit der benutzerdefinierten Prozedur my-map nach.

<eval id="4b1107f5e7ccf">(my-map sqr '(1 2 3 4 5 6 7 8 9 10))</eval>

Wir definieren die Bildungsvorschrift ungerader Zahlen und wenden sie mit my-map an:

<eval id="4b1107f5e8c73">(my-map ungerade '(1 2 3 4 5 6 7 8 9 10))</eval>

Es muss klar sein, dass auch unbenannte Prozeduren übergeben werden können:

<eval id="4b1107f5e9c11">(my-map (lambda (n) (+ (* 2 n) 1)) '(1 2 3 4 5 6 7 8 9 10))</eval>

Aufgaben

  1. Entwickeln Sie eine Prozedur höherer Ordnung, mit der die 3. Potenzen (Kubikzahlen) aller Elemente einer numerischen Liste berechnet werden können.

    <eval id="4b1107f5eabb0">(my-map kubik '(1 2 3 4 5 6 7 8 9 10))</eval>

  2. Entwickeln Sie die Prozedur (my-filter <proz> <ls>), mit der Elemente mit bestimmten Eigenschaften aus einer Zahlenliste herausgefiltert werden können.
    Testen Sie diese Prozedur mit dem Prädikat gerade?, z.B.:

    (my-filter gerade? '(1 2 3 4 5 6 7 8 9 10))
    --> (2 4 6 8 10)
    

    Hinweis: Mit der Prozedur modulo kann der Rest einer ganzzahligen Division ermittelt werden:

    (modulo 7 3)  --> 1
    (modulo 12 2) --> 0
    

    <eval id="4b1107f5ebb54">(my-filter gerade? '(1 2 3 4 5 6 7 8 9 10))</eval>

Zum Weiterarbeiten

Primzahlfilter

Mit einem Prädikat primzahl?, das zu einer natürlichen Zahl entscheidet, ob sie eine Primzahl ist, könnte die Prozedur my-filter aus einer Liste beliebiger natürlicher Zahlen alle Primzahlen herausfiltern.
Setzen Sie diese Idee um!

Zur Problemlösung.