i

Funktionsdefinition Schritt 4: Funktionsgerüst

Gerüst einer Funktion

In Schritten 1 bis 3 haben wir uns also mit der Modellierung der Funktion beschäftigt und diese in den Code eingebettet. Noch haben wir jedoch keine Funktion die wir tatsächlich aufrufen können. Hierfür entwerfen wir ein Gerüst.

Betrachten wir wieder unsere gewünschte Funktion als BlackBox-Diagramm: Testbild oder als Code. Dieser könnte nun beispielsweise wie folgt aussehen:
;Berechnet den flaecheninhalt eines Quaders in mm
(: flaecheninhalt (natural natural -> natural))
(check-expect (flaecheninhalt 125 20) 2500)
(check-expect (flaecheninhalt 125 0) 0)
Wir sehen anhand der Modellierungen unter anderem, dass die Funktion zwei Übergabebedaten übergeben bekommt. Unklar ist jedoch noch, wie wir diese Übergabedaten in der Funktion überhaupt verwenden können und wie wir die Funktion tatsächlich aufrufbar machen. In Racket gibt es hierfür zwei Schlüsselwörter, die wir für unsere Funktionsdefinition verwenden: define und lambda.

Schlüsselwort lambda

Aufgabe 1. Funktionsweise des Schlüsselworts lambda

Führe die folgenden Zeilen in der REPL aus. Kannst du dir die Ergebnisse erklären? Analysiere hierzu die einzelnen Ausdrücke. Achte dabei besonders auf die Klammerungen innerhalb der Ausdrücke.

    > ((lambda (x) (+ x x)) 3)

    > ((lambda (x) (* x x)) 3)

    > ((lambda (x y) (+ x y)) 2 3)

    > ((lambda (x y) (* (+ x y) y) 2 3)
    
Tipp: Schau dir gerne auch die Hilfestellung unter dieser Aufgabe an.

Hilfestellung zum Lambda-Ausdruck

Wir können uns Lambda als eine Funktion vorstellen, die eine beliebige Anzahl von Übergabebedaten erhält. Diese Übergabebedaten bekommen innerhalb von Lambda einen Namen. Testbild In der linken Abbildung erhält Lambda beispielsweise eine Übergabebedatum, welches den Namen $x$ erhält. In der rechten Abbildung erhält Lambda zwei Übergabebedaten, welche die Namen $x$ und $y$ erhalten. In Racket wäre dies entsprechend:

    (lambda (x) ...) ;links
    (lambda (x y) ...) ;rechts

    ;... fungieren als Platzhalter
    
Innerhalb von Lambda können Ausdrücke stehen, die die Namen der Übergabebedaten wiederverwenden. In unserem Beispiel die Ausdrücke $(+\ x\ x\ )$ links und $(*\ (+\ x\ y)\ y)$ rechts. Bzw. in Racket:
    (lambda (x) (+ x x)) ;links
    (lambda (x y) (* (+ x y) y)) ;rechts
Diese Ausdrücke, können wir dann wie gewohnt mit passenden Werten für die Übergabebedaten aufrufen.
    ((lambda (x) (+ x x)) 3) ;links
    ((lambda (x y) (* (+ x y) y)) 2 3) ;rechts
Testbild
Exkurs: Warum heißt das Schlüsselwort "lambda"?

Die Verwendung des griechischen Buchstaben lambda ($\lambda$) stammt aus dem mathematisch/informatischen $\lambda$-Kalkül. Hierzu in einem späteren Kapitel mehr.

Namensgebung der Übergabebedaten

Natürlich müssen die Namen nicht $x$ oder $y$ sein. Wir könnten also beispielsweise auch ein Lambda-Ausdruck wie folgt nennen:
    ((lambda (summand1 summand2) (+ summand1 summand2)) 20 22)
    

Schlüsselwort define

Aufgabe 2. Funktionsweise des Schlüsselwort define

Führe die Ausdrücke, nacheinander in der REPL aus. Welchen Zweck erfüllt das Schlüsselwort define?

    > (+ 2 vier)

    > (define vier 4)

    > (+ 2 vier)  

    > (addition 2 4)  

    > (define addition +)

    > (addition 2 4)

    > (anzahlZeichen "Hallo")

    > (define anzahlZeichen string-length)    

    > (anzahlZeichen "Hallo")

    > (addition (anzahlZeichen "Ich") vier)
    
Mit dem Schlüsselwort define, haben wir nun also die Möglichkeit einem (Atomaren)-Ausdruck einen Namen zuzuordnen, unter welchem wir diesen wiederverwenden können. Genauer gesagt, wir schreiben eine Definition für einen (Atomaren)-Ausdruck und geben dieser Definition einen Namen.

Aufgabe 3. Ändern von Definitionen

Was erwartest du wenn du die beiden unteren Ausdrücke in der REPL ausführst? Führe die Ausdrücke, nacheinander in der REPL aus und überprüfe deine Vermutung.

    > (define lieblingszahl 42)

    > (define lieblingszahl 17)
    
Achtung: Eine Definition ist keine Variable wie wir sie aus anderen Programmiersprachen kennen. Eine Definition ist immer konstant und kann nicht mehr verändert werden!

Das Gerüst - mit define und lambda

Um nun unser Gerüst für die Flächeninhaltsberechnung zu erstellen, kombinieren wir die Schlüsselwörter define und lambda. Hierzu geben wir einem Lambda-Ausdruck einfach einen Namen nach dem Prinzip:

(define nameFunktion
    (lambda (parameter1 ... parameterN)
        ...)) 
Diese Zeilen nennen wir das Gerüst einer Funktion.

Zusammenhang Signatur und Gerüst der Funktion

Auch bei der Erstellung des Gerüsts ist unsere vorangegangene Modellierung hilfreich.

Aufgabe 4. Zusammenhang Signatur und Gerüst

In der Signatur einer Funktion, stecken bereits zentrale Informationen, die wir für unsere Gerüst mit define und lambda verwenden können.

Vergleiche die Signatur und das Gerüst der drei Funktionen. Welche Parallelen kannst du feststellen?
a)

    ;Halbiert eine natürliche Zahl
    (: halbieren (natural -> rational))
    (check-expect (halbieren 4) 2)
    (check-expect (halbieren 9) 4.5)
    (define halbieren
    (lambda (zahl)
        ...))
    
b)
    ;Berechnet die Summe der Zeichen zweier Zeichenketten
    (: summeZweierZeichenketten (string string -> natural))
    (check-expect (summeZweierZeichenketten "Hallo" "Welt") 9)
    (check-expect (summeZweierZeichenketten "Informatik ist cool" "") 19)
    (define summeZweierZeichenketten
    (lambda (wort1 wort2)
        ...))
    
c)
    ;Berechnet das Produkt dreier Zahlen
    (: produktDreiZahlen (real real real -> real))
    (check-expect (produktDreiZahlen 12 10 0) 0)
    (check-expect (produktDreiZahlen 5 7.6 -14.1) -535.8)
    (define produktDreiZahlen
    (lambda (x y z)
        ...))
    
Wir merken uns:
1. Der Name der Funktion in der Signatur muss mit der Definition von define übereinstimmen.
2. Die Anzahl an Parametern von lambda, muss exakt der Anzahl der Übergabebedaten entsprechen.
Wenn wir die Signatur bereits haben geht das Gerüst schreiben also fast von selbst! Wir müssen uns lediglich geeignete Namen für die Übergabebedaten ausdenken, alles andere ist uns fest vorgegeben.

Aufgabe 5. Gerüst der Flächeninhaltsberechnung

Schreibe in dein Definitionsfenster unter deine Testfälle das Gerüst für unsere Flächeninhaltsberechnung. Denke dir dabei geeignete Namen für die Übergabebedaten aus.

Übungsaufgaben

Aufgabe 6. Erstellen von geeigneten Gerüsten

Schreibe in dein Definitionsfenster das Gerüst unter deine Testfälle der Modellierungen folgender Funktionen: (Aufgabe 3. und 4. im vorangegangenen Kapitel)

  1. Die Funktion quadrieren
  2. Die Funktion korrekteAnzahlBuchstaben?
  3. Der Funktion die den Durchschnitt zweier ganzer Zahlen berechnen soll.
  4. Der Funktion die bestimmt, ob ein Text eine gerade Anzahl an Buchstaben hat.

Suche

v
100.137.1.2.3.4
https://inf-schule.de/entwuerfe/racket/einfuehrung/programmiersprache_racket/funktionsdefinitionen/geruest
https://inf-schule.de/100.137.1.2.3.4
https://inf-schule.de/@/page/XCCiGa2enKBGMYGg

Rückmeldung geben