Grundlagen der funktionsorientierten Programmierung mit SCHEME/Prozeduren

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>
== Definition von Prozeduren ==

Um Kreisflächen beliebiger Radien zu bestimmen, war bisher immer die Neudefinition des Radiusses notwendig.<br />
Wie kann der Radius als ''Argument'' übergeben werden?

'''Lösungsidee:'''

Definiere eine ''Prozedur'', die ähnlich einer mathematischen Funktion einen Funktionswert zurückgibt.

<table border="0" cellspacing="0" cellpadding="0">
<tr>
<th align="left" valign="top">Mathematik:</th>
<td>
<math>flaeche: r \longrightarrow \pi \cdot r^2</math><br />
oder:<br />
<math>flaeche(r) = \pi \cdot r^2</math><br />
</td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<th align="left" valign="top">Funktionsorientierte Programmierung:</th>
<td>
[[Bild:Flaechenberechnung.gif]]
</td>
</tr>
</table>

'''Implementation:'''

<code id="4c72e4c772284">
(define pi (* 4 (atan 1)))

(define flaeche	
  (lambda (r)
    (* pi r r)))

;Alternative:
;(define (flaeche r)
;  (* pi r r))
</code>

Wir überzeugen uns zunächst davon, dass wir tatsächlich eine Prozedur definiert haben:

<run id="4c72e4c7723b0">
flaeche
</run>

Nun können wir Berechnungen mit beliebigen Radien vornehmen:

<run id="4c72e4c7724d2">
(flaeche 10)
</run>

'''Interpretation:'''<br />
* Die Prozedur <tt>(lambda (r) (* pi r r))</tt> wird an den Namen <tt>flaeche</tt> gebunden.
* Der Parameter <tt>r</tt> heißt ''gebundene'' Variable.
* Die Variablen <tt>*</tt> und <tt>pi</tt> sind dagegen ''ungebunden'' oder ''frei''.

'''Beachte:'''<br />
Die Bindung einer Prozedur an einen Namen heißt ''Prozedurabstraktion''. Sie ist aber nicht notwendig!<br />
In Scheme können auch ''unbenannte'' Prozeduren verwendet werden:

<run id="4c72e4c7725db">
(lambda (x) (* x x))
</run>

<run id="4c72e4c7726ec">
((lambda (x) (* x x)) 12)
</run>

=== Zusammenfassung ===

* Benutzerdefinierte Prozeduren werden mit ''&lambda;-Ausdrücken'' definiert.
* Allgemeine Syntax: <tt>(lambda (<Parameter>) <Body>)</tt>.
* Die Anzahl der Parameter kennzeichnet die ''Stelligkeit'' einer Prozedur. Ist die Parameterliste leer, spricht man von ''nullstelligen'' Prozeduren,
* Die Parameter sind gebundene Variablen, die beliebig bezeichnet werden können, sofern sie nicht mit freien Variablen im Körper übereinstimmen.
* &lambda;-Ausdrücke können an Prozedurnamen gebunden werden (''Prozedurabstraktion'').

== Aufgaben ==

<code id="4c7eb87d68027" hidden>
(define eps 1e-03)

(define sqr
  (lambda (x)
    (* x x)))

(define test-runden
  (lambda (x anzahl)
    (/ (round (* x (expt 10 anzahl))) (expt 10 anzahl))))

(define test-flaeche 
  (lambda (radius)
    (* pi radius radius)))

(define test-volumen-vollzylinder 
  (lambda (radius hoehe)
    (* (test-flaeche radius) hoehe)))

(define test-volumen-hohlzylinder 
  (lambda (radius1 radius2 hoehe)
    (- (test-volumen-vollzylinder radius1 hoehe) (test-volumen-vollzylinder radius2 hoehe))))

(define test-volumen-quadpyramide
  (lambda (seite hoehe)
    (* 1/3 seite seite hoehe)))

(define test-oberflaeche-quadpyramide
  (lambda (seite hoehe)
    (* seite (+ seite (* 2 (sqrt (+ (sqr (/ seite 2)) (sqr hoehe))))))))

(define test-volumen-quadpyramidenstumpf
  (lambda (seite hoehe stumpfhoehe)    
    (- (test-volumen-quadpyramide seite hoehe) 
       (test-volumen-quadpyramide (* (- 1 (/ stumpfhoehe hoehe)) seite) (- hoehe stumpfhoehe)))))

(define test-oberflaeche-quadpyramidenstumpf
  (lambda (seite hoehe stumpfhoehe)
    (- (test-oberflaeche-quadpyramide seite hoehe) 
       (test-oberflaeche-quadpyramide 
         (* (- 1 (/ stumpfhoehe hoehe)) seite) (- hoehe stumpfhoehe)) 
         (* -2 (sqr (* (- 1 (/ stumpfhoehe hoehe)) seite))))))
</code>

<ol>
<li>
=== Sinnvolles Runden ===

Für alle nachfolgenden Berechnungen ist es sinnvoll, über eine Prozedur zu verfügen, die auf eine ''beliebige'' Anzahl von Nachkommastellen rundet.<br />
'''Beispiele:'''
<pre>
(runden 12.3456 2)  --> 12.35
(runden 0.005712 3) --> 0.006
</pre>

Nutzen Sie zur Implementation die Standard-Prozedur <tt>round</tt>, die lediglich ganzzahlig rundet.

<code id="4c7eb87d6815d">
(define runden
  (lambda (x anzahl)
    ...))
</code>

<check>
(and (= (runden 12.3456 2) 12.35) (= (runden 0.005712 3) 0.006))
</check>

<run id="4c7eb87d682c5">
(runden 12.3456 2)
</run>
</li>
<li>
=== Vollzylinder ===

Schreiben Sie eine Prozedur zur Volumenberechnung eines geraden Vollzylinders.

<code id="4c736c6335cf3">
(define volumen-vollzylinder
  (lambda (radius hoehe)
    ...))
</code>

<check>
(< (abs (- (volumen-vollzylinder 13 55) (test-volumen-vollzylinder 13 55))) eps)
</check>

<run id="4c736c6335f54">
(volumen-vollzylinder 7 28)
</run>
</li>
<li>
=== Hohlzylinder ===

Implementieren Sie nun eine Prozedur zur Volumenberechnung eines geraden Hohlzylinders.

<code id="4c736c6335e13">
(define volumen-hohlzylinder
  (lambda (radius1 radius2 hoehe)
    ...))
</code>

<check>
(< (abs (- (volumen-hohlzylinder 13 7 55) (test-volumen-hohlzylinder 13 7 55))) eps)
</check>

<run id="4c7eb922c0443">
(volumen-hohlzylinder 7 6 28)
</run>
</li>
<li>
=== Pyramide und Pyramidenstumpf ===

Definieren Sie zunächst die Prozedur zur Berechnung des Volumens und der Oberfläche gerader quadratischer Pyramiden.

<code id="4c7540a6484bf">
(define volumen-quadpyramide
  (lambda (seite hoehe)
    ...))
</code>

<check>
(< (abs (- (volumen-quadpyramide 5.5 17.5) (test-volumen-quadpyramide 5.5 17.5))) eps)
</check>

<run id="4c7eb922c058d">
(volumen-quadpyramide 5.5 17.5)
</run>

<code id="4c7c9a3f2101a">
(define oberflaeche-quadpyramide
  (lambda (seite hoehe)
    ...))
</code>

<check>
(< (abs (- (oberflaeche-quadpyramide 5.5 17.5) (test-oberflaeche-quadpyramide 5.5 17.5))) eps)
</check>

<run id="4c7eb922c06c1">
(oberflaeche-quadpyramide 5.5 17.5)
</run>

<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="250" align="center">
[[Bild:Pyramide1.gif]]
</td>
<td width="350" valign="top">
In einer nun geringeren Höhe wird die Spitze der quadratischen Pyramide abgeschnitten.<br />
Zurück bleibt ein Pyramidenstumpf.<br />
Schreiben Sie zwei Prozeduren, die entsprechend dieser Vorstellung das Volumen und den Oberflächeninhalt des Pyramidenstumpfes ermitteln.
</td>
</tr>
</table>

<code id="4c754364265d2">
(define volumen-quadpyramidenstumpf
  (lambda (seite hoehe stumpfhoehe)    
    ...))
</code>

<check>
(< (abs (- (volumen-quadpyramidenstumpf 5.5 17.5 9.0) (test-volumen-quadpyramidenstumpf 5.5 17.5 9.0))) eps)
</check>

<run id="4c7eb922c07fd">
(volumen-quadpyramidenstumpf 5.5 17.5 9.0)
</run>

<code id="4c7c9a3f21150">
(define oberflaeche-quadpyramidenstumpf
  (lambda (seite hoehe stumpfhoehe)    
    ...))
</code>

<check>
(< (abs (- (oberflaeche-quadpyramidenstumpf 5.5 17.5 9.0) (test-oberflaeche-quadpyramidenstumpf 5.5 17.5 9.0))) eps)
</check>

<run id="4c7eb922c0937">
(oberflaeche-quadpyramidenstumpf 5.5 17.5 9.0)
</run>
</li>
</ol>