Es werden zwei Arten von Funktionen unterschieden:
function <function_name> (<parameter>, ...)
<statements zu Ausführung der Funktion>
end
<function_name> | Der Name einer Funktion entspricht in seinem Aufbau dem eines Symbols. |
<parameter> | Bei den Parametern handelt es sich um Symbole beliebigen Typs, welche in der Funktion nicht vereinbart werden. Die Zulässigkeit des Typs eines Parameters wird wie bei allen Symbolen zum Zeitpunkt der Ausführung in einem Ausdruck geprüft. Die Klammern nach dem Funktionsnamen sind auch dann notwendig, wenn die Funktion keine Parameter benötigt. Wird von der rufenden Funktion ein Parameter nicht angegeben, was zulässig ist, so besitzt er den Wert "invalid". |
AQL behandelt alle Parameter als Ausdrücke und versorgt die gerufene Funktion mit einem Hilfssymbol, das das Ergebnis enthält (call by value) oder mit der Referenz (Zeiger) auf das Original-Symbol bei vorangestelltem Schlüsselwort var in der Aufrufleiste (call by reference). Das heißt, wenn die Funktion diese manipuliert, wird auch der Wert der Variablen in der aufrufenden Funktion manipuliert.
function my_function (var reference_parameter, value_parameter)
....
Jede Funktion liefert dem verwendenden Programm einen Funktionswert. Dieser Funktionswert wird behandelt wie das Ergebnis eines Ausdrucks. Damit können Funktionsaufrufe in Ausdrücke integriert werden, welche u.U. auch wiederum Funktionsparameter sein können. In einer Funktionsdeklaration wird der Rückgabewert als Argument der return-Anweisung definiert. Erfolgt der Rücksprung aus einer Funktion nicht über ein "return" mit Argument, so ist der Funktionswert invalid. Fehlt das return, so erfolgt der Rücksprung bei der end-Anweisung.
Jede Funktion wird wie das Hauptprogramm behandelt und umgekehrt, d.h. sie kann Symbol- und Funktionsvereinbarungen enthalten. Wie in PASCAL sind auch geschachtelte Funktionsdeklarationen möglich. Bei größeren AQL-Programmen ist auf besondere Sorgfalt bei der Verwendung globaler Symbole zu achten.
PROGRAMM: | AUSGABE: |
---|---|
function noparam() | |
‘function with no parameters‘ nl | |
end | |
noparam() | function with no parameters |
function noretvalue() | |
‘function noretvalue with no return value‘ nl | |
end | |
[type(noretvalue())] nl | function noretvalue with no return value |
invalid | |
function retvalue() | |
return ("function retvalue returns this string") | |
end | |
[retvalue()] nl | function retvalue returns this string |
function param(first_par,second_par) | |
if not valid(first_par) then | |
first_par = "not given" | |
end | |
if not valid(second_par) then | |
second_par = "not given" | |
end | |
‘function param with parameter:‘ | |
[first_par]‘,‘[second_par] nl | |
end | |
param(1,2) | function param with parameter:1,2 |
param(1,) | function param with parameter:1,not given |
param(,) | function param with parameter:not given,not given |
function my_function (<parameter>, ...) forward
Hiermit kann eine Funktion im voraus ohne Inhalt vereinbart werden. Dabei muß die Anzahl der Argumente dieser Deklaration mit der Anzahl der Argumente bei der Deklaration der Funktion mit dem Inhalt übereinstimmen. Diese Form ist dann angebracht, wenn sich rekursive Funktionen gegenseitig aufrufen:
function a (count) forward
function b (count)
if count != 0 then a(count-1) end
end
function a (count)
if count != 0 then b(count-1) end
end
Die Verwendung ist in vier Formen zulässig:
Die erste und zweite Form sind in ihrer Wirkungsweise gleich. Hier wird ein Funktionswert invalid zurückgeliefert.
return
return()
Bei der dritten Form spezifiziert der Ausdruck den Funktionswert. Ein return im Hauptprogramm bewirkt die Beendigung des Hauptprogramms.
return (<return_value_expression>)
Bei der vierten Form wird der Rückgabewert des AQL-Programms an ein aufrufendes AQL-Programm geliefert. Ein Rücksprung ins aufrufende AQL-Programm erfolgt jedoch erst durch eine return-Anweisung oder bei Erreichen des Dateiendes.
return_code (<integer>)
Um Programme variabel zu gestalten kann mit sogenannnten Funktionszeigern gearbeitet werden. Die allgemeine Form der Anweisung ist:
fp = FUNCTION <my_function>
Der Aufruf einer Funktion kann in Form einer Anweisung erfolgen. Die Funktion wird anhand ihres Namens oder anhand des Funktionszeigers identifiziert.
<function_name> ([<parameter>,...])
oder
<function_pointer> ([<parameter>, ...]) ...
Dabei wird ein möglicher Funktionswert ignoriert. Soll der Funktionswert weiterverarbeitet werden, so ist die folgende Form des Ausdrucks zu wählen:
<symbol> <operator> <function_name> ([<parameter>,...]) ...
Dabei ist zu berücksichtigen, daß die verwendete Funktion einen Funktionswert liefert und daß dieser im Umfeld seiner Verwendung typverträglich ist. Jede Funktion muß vor ihrer Verwendung vereinbart worden sein. Die Rekursion – die Verwendung einer Funktion durch sich selbst – ist möglich, wie im folgenden klassischen Beispiel gezeigt wird.
PROGRAMM: |
---|
function hanoi(stack, from, to, use) |
if empty(stack.tail) then |
‘moving ‘[stack.first;-6] |
‘ block from ‘[from;-]‘ to ‘[to] nl; |
else |
hanoi(stack.tail, from, use, to) |
hanoi({stack.first}, from, to, use) |
hanoi(stack.tail, use , to, from) |
end |
end |
hanoi( {"red" "green" "blue"}, "source ", "target ", "parking") |
AUSGABE: |
---|
moving blue block from source to target |
moving green block from source to parking |
moving blue block from target to parking |
moving red block from source to target |
moving blue block from parking to source |
moving green block from parking to target |
moving blue block from source to target |
◀ Kontrollanweisungen | Fuktionen ▶ |