Suche…


Einführung

Eine benutzerdefinierte Funktion in Progress ABL ist ein wiederverwendbares Programmmodul.

Bemerkungen

  • Eine Funktion muss in der "Haupt" -Prozedur deklariert werden. Es kann nicht innerhalb einer Prozedur oder einer anderen Funktion deklariert werden.
  • Eine Funktion in Progress ABL ist im Gegensatz zu Programmiersprachen wie Haskell oder Javascript kein "erstklassiger Bürger". Sie können eine Funktion nicht als Eingabe- oder Ausgabeparameter übergeben. Sie können sie jedoch dynamisch mit DYNAMIC-FUNCTION oder dem CALL Objekt DYNAMIC-FUNCTION .
  • Das Aufrufen von Funktionen in Ihren Abfragen kann zu einer schlechten Leistung führen, da der Indexabgleich verletzt wird. Versuchen Sie, den Wert der Funktion einer Variablen zuzuweisen, und verwenden Sie diese Variable stattdessen in der WHERE -clause.

Einfache Funktion

/* This function returns TRUE if input is the letter "b" and false otherwise */
FUNCTION isTheLetterB RETURNS LOGICAL (INPUT pcString AS CHARACTER):
  IF pcString = "B" THEN 
    RETURN TRUE.
  ELSE 
    RETURN FALSE.
END FUNCTION.

/* Calling the function with "b" as input - TRUE expected */
DISPLAY isTheLetterB("b").

/* Calling the function with "r" as input - FALSE expected */
DISPLAY isTheLetterB("r").

Teile der Syntax sind eigentlich nicht erforderlich:

/* RETURNS isn't required, INPUT isn't required on INPUT-parameters */
FUNCTION isTheLetterB LOGICAL (pcString AS CHARACTER):
  IF pcString = "B" THEN 
    RETURN TRUE.
  ELSE 
    RETURN FALSE.
/* END FUNCTION can be replaced with END */
END.

Weiterleiten deklarierender Funktionen

Eine Funktion kann vorwärts deklariert werden, dies entspricht den Angaben in einer C-Header-Datei. Auf diese Weise weiß der Compiler, dass später eine Funktion zur Verfügung gestellt wird.

Ohne Forward-Deklarationen MUSS die Funktion deklariert werden, bevor sie im Code aufgerufen wird. Die Vorwärtsdeklaration besteht aus der FUNCTION Spezifikation (Funktionsname, Rückgabetyp und Parameterdatentypen und Reihenfolge). Wenn die Vorwärtsdeklaration nicht mit der tatsächlichen Funktion übereinstimmt, erzeugt der Compiler Fehler und der Code kann nicht ausgeführt werden.

FUNCTION dividableByThree LOGICAL (piNumber AS INTEGER) FORWARD.

DISPLAY dividableByThree(9).

FUNCTION dividableByThree LOGICAL (piNumber AS INTEGER):

    IF piNumber MODULO 3 = 0 THEN
        RETURN TRUE.
    ELSE 
        RETURN FALSE.
END.

Mehrere Eingabeparameter

/ * Ein Popup-Fenster mit der Meldung "HELLO WORLD" wird angezeigt. * /

FUNCTION cat RETURNS CHARACTER ( c AS CHARACTER, d AS CHARACTER):

    RETURN c + " " + d.

END.

MESSAGE cat("HELLO", "WORLD") VIEW-AS ALERT-BOX.

Mehrere return-Anweisungen (aber ein einzelner Rückgabewert)

Eine Funktion kann mehrere return-Anweisungen haben und sie können in verschiedenen Teilen der eigentlichen Funktion platziert werden. Sie müssen jedoch alle denselben Datentyp zurückgeben.

FUNCTION returning DATE ( dat AS DATE):
    IF dat < TODAY THEN DO:
        DISPLAY "<".
        RETURN dat - 200.
    END.
    ELSE DO:
        DISPLAY ">".
        RETURN TODAY. 
    END.
END.

MESSAGE returning(TODAY + RANDOM(-50, 50)) VIEW-AS ALERT-BOX.

Eine Funktion muss überhaupt nichts zurückgeben. Dann wird es Rückgabewert sein? (unbekannte). Der Compiler wird das nicht fangen (aber Ihre Kollegen werden es vermeiden).

/* This function will only return TRUE or ?, never FALSE, so it might lead to troubles */
FUNCTION inTheFuture LOGICAL ( dat AS DATE):
    IF dat > TODAY THEN DO:
        RETURN TRUE.
    END.
END.
MESSAGE inTheFuture(TODAY + RANDOM(-50, 50)) VIEW-AS ALERT-BOX.

Ausgabe- und Eingabe-Ausgabe-Parameter

Eine Funktion kann nur einen einzelnen Wert zurückgeben, aber es gibt eine Möglichkeit: Die Parameter sind nicht auf Eingabeparameter beschränkt. Sie können die Parameter INPUT , OUTPUT und INPUT-OUTPUT .

Im Gegensatz zu den INPUT Parametern müssen Sie OUTPUT oder INPUT-OUTPUT vor den Parametern angeben.

Einige Codierungskonventionen mögen dies nicht mögen, aber es ist möglich.

/* Function will add numbers and return a sum (AddSomSumbers(6) = 6 + 5 + 4 + 3 + 2 + 1 = 21 */
/* It will also have a 1% per iteration of failing                                           */
/* To handle that possibility we will have a status output parameter                         */
FUNCTION AddSomeNumbers INTEGER ( INPUT number AS INTEGER, OUTPUT procstatus AS CHARACTER):
    
    procStatus = "processing".

    DEFINE VARIABLE i AS INTEGER     NO-UNDO.
    DEFINE VARIABLE n AS INTEGER     NO-UNDO.
    /* Iterate number times */
    DO i = 1 TO number:
        /* Do something */

        n = n + i.
        
        /* Fake a 1% chance for an error that breaks the function */
        IF RANDOM(1,100) = 1 THEN
            RETURN 0.
    END.

    procStatus = "done".
    RETURN n.
END.


DEFINE VARIABLE ret   AS INTEGER     NO-UNDO.
DEFINE VARIABLE stat  AS CHARACTER   NO-UNDO.

/* Call the function */
ret = AddSomeNumbers(30, OUTPUT stat).

/* If "stat" is done we made it! */
IF stat = "done" THEN DO:
    MESSAGE "We did it! Sum:" ret VIEW-AS ALERT-BOX.
END.
ELSE DO:
    MESSAGE "An error occured" VIEW-AS ALERT-BOX ERROR.
END.

Hier ist ein Beispiel eines INPUT-OUTPUT Parameters:

/* Function doubles a string and returns the length of the new string */
FUNCTION doubleString RETURN INTEGER (INPUT-OUTPUT str AS CHARACTER).

    str = str + str.

    RETURN LENGTH(str).

END.

DEFINE VARIABLE str AS CHARACTER   NO-UNDO.
DEFINE VARIABLE len AS INTEGER     NO-UNDO.

str = "HELLO".

len = doubleString(INPUT-OUTPUT str).

MESSAGE 
    "New string: " str SKIP
    "Length: " len VIEW-AS ALERT-BOX.

Rekursion

Siehe Rekursion

Eine Funktion kann sich selbst aufrufen und dadurch wiederkehren.

FUNCTION factorial INTEGER (num AS INTEGER).

    IF num = 1 THEN 
        RETURN 1.
    ELSE 
        RETURN num * factorial(num - 1).

END FUNCTION.

DISPLAY factorial(5).

Mit Standardeinstellungen (Startparameter) kann die Fortschrittssitzung in diesem Beispiel nicht mit sehr großen Zahlen umgehen. factorial(200) füllt den Stapel und löst einen Fehler aus.

Dynamischer Aufruf einer Funktion

Mit DYNAMIC-FUNCTION oder dem CALL -Objekt können Sie Funktionen dynamisch aufrufen.

DEFINE VARIABLE posY      AS INTEGER     NO-UNDO.
DEFINE VARIABLE posX      AS INTEGER     NO-UNDO.
DEFINE VARIABLE OKkeys    AS CHARACTER   NO-UNDO INIT "QLDRUS".
DEFINE VARIABLE Step      AS INTEGER     NO-UNDO INIT 1.
DEFINE VARIABLE moved     AS LOGICAL     NO-UNDO.
/* Set original position */
posY = 10.
posX = 10.

/* Move up (y coordinates - steps ) */
FUNCTION moveU LOGICAL (INPUT steps AS INTEGER):

    IF posY = 0 THEN
        RETURN FALSE.

    posY = posY - steps.

    IF posY < 0 THEN
        posY = 0.

    RETURN TRUE.
END FUNCTION.

/* Move down (y coordinates + steps ) */
FUNCTION moveD LOGICAL (INPUT steps AS INTEGER):

    IF posY = 20 THEN
        RETURN FALSE.

    posY = posY + steps.

    IF posY > 20 THEN
        posY = 20.
        
END FUNCTION.

/* Move left (x coordinates - steps ) */
FUNCTION moveL LOGICAL (INPUT steps AS INTEGER):

    IF posX = 0 THEN
        RETURN FALSE.

    posX = posX - steps.

    IF posX < 0 THEN
        posX = 0.

    RETURN TRUE.
END FUNCTION.

/* Move down (x coordinates + steps ) */
FUNCTION moveR LOGICAL (INPUT steps AS INTEGER):

    IF posX = 20 THEN
        RETURN FALSE.

    posX = posX + steps.

    IF posX > 20 THEN
        posX = 20.
        
END FUNCTION.


REPEAT:

    DISPLAY posX posY step WITH FRAME x1 1 DOWN.
    READKEY.

    IF INDEX(OKKeys, CHR(LASTKEY)) <> 0 THEN DO:
        IF CHR(LASTKEY) = "q"  THEN LEAVE.
        IF CAPS(CHR(LASTKEY)) = "s" THEN UPDATE step WITH FRAME x1.
        ELSE DO:
            moved = DYNAMIC-FUNCTION("move" + CAPS(CHR(LASTKEY)), INPUT step).
            IF moved = FALSE THEN
                MESSAGE "Out of bounds".
        END.
    END.
END.

Das CALL Objekt ist nicht so leicht wie die DYNAMIC-FUNCTION. Es kann verwendet werden, um verschiedene Dinge aufzurufen: Funktionen, Prozeduren, externes Programm, Windows-DLL-Funktionen. Es kann auch Methoden für Objekte aufrufen und auf Getter / Setter zugreifen.

DEFINE VARIABLE functionHandle AS HANDLE      NO-UNDO.
DEFINE VARIABLE returnvalue    AS CHARACTER   NO-UNDO.

FUNCTION isPalindrome LOGICAL (INPUT txt AS CHARACTER, OUTPUT txtBackwards AS CHARACTER):
    DEFINE VARIABLE i AS INTEGER     NO-UNDO.

    DO i = LENGTH(txt) TO 1 BY -1:
        txtBackwards = txtBackwards + SUBSTRING(txt, i, 1).
    END.

    IF txt = txtBackwards THEN
        RETURN TRUE.
    ELSE 
        RETURN FALSE.

END FUNCTION.

CREATE CALL functionHandle.
functionHandle:CALL-NAME      = "isPalindrome".
/* Sets CALL-TYPE to the default */
functionHandle:CALL-TYPE  = FUNCTION-CALL-TYPE.
functionHandle:NUM-PARAMETERS = 2.
functionHandle:SET-PARAMETER(1, "CHARACTER", "INPUT", "HELLO WORLD").
functionHandle:SET-PARAMETER(2, "CHARACTER", "OUTPUT", returnvalue). 
functionHandle:INVOKE.

MESSAGE "Text backwards: " returnvalue "Is it a palindrome? " functionHandle:RETURN-VALUE VIEW-AS ALERT-BOX.

DELETE OBJECT functionHandle.


CREATE CALL functionHandle.
functionHandle:CALL-NAME      = "isPalindrome".
/* Sets CALL-TYPE to the default */
functionHandle:CALL-TYPE  = FUNCTION-CALL-TYPE.
functionHandle:NUM-PARAMETERS = 2.
functionHandle:SET-PARAMETER(1, "CHARACTER", "INPUT", "ANNA").
functionHandle:SET-PARAMETER(2, "CHARACTER", "OUTPUT", returnvalue). 
functionHandle:INVOKE.

MESSAGE "Text backwards: " returnvalue "Is it a palindrome? " functionHandle:RETURN-VALUE VIEW-AS ALERT-BOX.

DELETE OBJECT functionHandle.


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow