Datentyp "Function", Funktionsliteral und Funktion als Eingabeparameter

In der Definition der Gesamtkurvenfunktion wurde die spezielle Basiskurvenfunktion baseCurve verwendet.
Man könnte nun verschiedene Basiskurvenfunktionen definieren aus denen je nach Anforderung beim Aufruf der Gesamtkurvenfunktion eine bestimmte Basiskurve verwendet wird.
Die Basiskurvenfunktion wird somit zum Eingabeparameter für die Gesamtkurvenfunktion.

1. Veränderung: Variable vom Typ "Function"

Codeabschnitte, die sich nicht vom vorigen Arbeitsschritt unterscheiden, werden grau geschrieben.

....

/*
ZEICHNEN EINER WELLENLINIE
*/
var point = new Array();
point.x = 0;
point.y = Stage.height/2;
var wave:Function = baseCurve;
curve(point, 45, 200, 1, 0x000000);
/*
DEKLARATION DER FUNKTIONEN curve(), baseCurve() UND fillStage()
*/
function curve(pt:Array, a:Number, b:Number, lineWidth:Number, lineColor:Number):Void {
   this.lineStyle(lineWidth, lineColor);
   this.moveTo(pt.x, pt.y);
   do {
      pt = wave(pt, a, b);
   } while (0<=pt.x && pt.x<Stage.width && 0<=pt.y && pt.y<Stage.height);
}
function baseCurve(pt:Array, a:Number, b:Number):Array {
   this.curveTo(pt.x+a/4, pt.y-b/2, pt.x+a/2, pt.y);
   this.curveTo(pt.x+3*a/4, pt.y+b/2, pt.x+a, pt.y);
   pt.x = pt.x+a;
   return pt;
}

....

Durch var wave:Function = baseCurve; wird eine Variable vom Typ Function definiert, der die Funktion baseCurve zugeordnet wird.
Über die Variable wave kann nun die Funktion baseCurve aufgerufen werden.

In der Funktionsdefinition von curve wird in pt = wave(pt, a, b); über die Funktionsvariable wave die Funktion aufgerufen, die der Variablen zugeordnet wurde. In unserem Fall die Funktion baseCurve.
wave ist in diesem Fall eine "versteckte" Eingabe für die Funktion curve, die nicht über die Eingabeparameter übergeben wird. Das ist wieder ein Seiteneffekt.

Je nachdem welche Funktion der Varibalen wave zugeordnet wurde, wird eine andere Gesamtkurve gezeichnet.

 

2. Veränderung: Basisfunktion als Eingabeparameter für die Gesamtkurve

....

/*
ZEICHNEN EINER WELLENLINIE
*/
var point = new Array();
point.x = 0;
point.y = Stage.height/2;
curve(baseCurve, point, 45, 200, 1, 0x000000);
/*
DEKLARATION DER FUNKTIONEN curve(), baseCurve() UND fillStage()
*/
function curve(bc:Function, pt:Array, a:Number, b:Number, lineWidth:Number, lineColor:Number):Void {
   this.lineStyle(lineWidth, lineColor);
   this.moveTo(pt.x, pt.y);
   do {
      pt = bc(pt, a, b);
   } while (0<=pt.x && pt.x<Stage.width && 0<=pt.y && pt.y<Stage.height);
}
function baseCurve(pt:Array, a:Number, b:Number):Array {
   curveTo(pt.x+a/4, pt.y-b/2, pt.x+a/2, pt.y);
   curveTo(pt.x+3*a/4, pt.y+b/2, pt.x+a, pt.y);
   pt.x = pt.x+a;
   return pt;
}

....

In der Funktionsdefinition von curve wird ein neuer Eingabeparameter bc vom Typ Function eingeführt über den die Basiskurvenfunktion übergeben wird.
In pt = bc(pt, a, b); wird über die Funktionsvariable bc die übergebene Basiskurvenfunktion aufgerufen.

Im Funktionsaufruf curve(baseCurve, point, 45, 200, 1, 0x000000); wird die Funktion baseCurve als Eingabeparameter übergeben.

In der Funktionsdefinition von baseCurve ist es wichtig, dass in diesem Fall this.curveTo(...) durch curveTo(...) ersetzt wird.

 

3. Veränderung: Defintion der Basiskurve als Funktionsliteral

....

/*
ZEICHNEN EINER WELLENLINIE
*/
var point = new Array();
point.x = 0;
point.y = Stage.height/2;
var wave:Function = function (pt:Array, a:Number, b:Number):Array {
   curveTo(pt.x+a/4, pt.y-b/2, pt.x+a/2, pt.y);
   curveTo(pt.x+3*a/4, pt.y+b/2, pt.x+a, pt.y);
   pt.x = pt.x+a;
   return pt;
};
curve(wave, point, 45, 200, 1, 0x000000);
/*
DEKLARATION DER FUNKTIONEN curve(), baseCurve() UND fillStage()
*/
function curve(bc:Function, pt:Array, a:Number, b:Number, lineWidth:Number, lineColor:Number):Void {
   this.lineStyle(lineWidth, lineColor);
   this.moveTo(pt.x, pt.y);
   do {
      pt = bc(pt, a, b);
   } while (0<=pt.x && pt.x<Stage.width && 0<=pt.y && pt.y<Stage.height);
}
....

Ein Funktionsliteral ist eine unbenannte (anonyme) Funktion, die man in einem Ausdruck deklariert.
Man kann ein Funktionsliteral in einer Variablen speichern und später im Code wieder darauf zugreifen.

In unserem Fall ist das Funktionsliteral

function (pt:Array, a:Number, b:Number):Array {
   curveTo(pt.x+a/4, pt.y-b/2, pt.x+a/2, pt.y);
   curveTo(pt.x+3*a/4, pt.y+b/2, pt.x+a, pt.y);
   pt.x = pt.x+a;
   return pt;
}

das in der Variablen wave abgespeichert wird:
var wave:Function = function (pt:Array, a:Number, b:Number):Array {...};

Über Funktionsliterale werden in Regel den Eventhandlern für z.B. die Maus- oder Tastaturereignisse Funktionen zugewiesen.

 

4. Veränderung: Ein Funktionsliteral als Eingabewert der Gesamtkurvenfunktion

Man kann sogar ein Funktionsliteral als Eingabeparameter an eine andere Funktion übergeben.

....

/*
ZEICHNEN EINER WELLENLINIE
*/
var point = new Array();
point.x = 0;
point.y = Stage.height/2;
curve(function (pt:Array, a:Number, b:Number):Array {
         curveTo(pt.x+a/4, pt.y-b/2, pt.x+a/2, pt.y);
         curveTo(pt.x+3*a/4, pt.y+b/2, pt.x+a, pt.y);
         pt.x = pt.x+a;
         return pt;
      }, point, 45, 200, 1, 0x000000);
/*
DEKLARATION DER FUNKTIONEN curve(), baseCurve() UND fillStage()
*/
function curve(bc:Function, pt:Array, a:Number, b:Number, lineWidth:Number, lineColor:Number):Void {
   this.lineStyle(lineWidth, lineColor);
   this.moveTo(pt.x, pt.y);
   do {
      pt = bc(pt, a, b);
   } while (0<=pt.x && pt.x<Stage.width && 0<=pt.y && pt.y<Stage.height);
}
....

In diesem Beispiel wurde die Basiskurve direkt im Funktionsaufruf der Gesamtkurve als Funktionsliteral definiert und als Parameter übergeben.