Zoeken…


Invoering

Een door de gebruiker gedefinieerde functie in Progress ABL is een herbruikbare programmamodule.

Opmerkingen

  • Een functie moet worden aangegeven in de "hoofd" procedure. Het kan niet binnen een procedure of binnen een andere functie worden gedeclareerd.
  • Een functie in Progress ABL is geen "eerste klas burger" in tegenstelling tot programmeertalen zoals Haskell of Javascript. U kunt een functie niet doorgeven als invoer- of uitvoerparameter. U kunt ze echter dynamisch oproepen met DYNAMIC-FUNCTION of het CALL object.
  • Belfuncties in uw query's kunnen leiden tot slechte prestaties, omdat indexafstemming pijn doet. Probeer de waarde van de functie toe te wijzen aan een variabele en gebruik in plaats daarvan die variabele in de WHERE -clausule.

Eenvoudige functie

/* 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").

Delen van de syntaxis zijn eigenlijk niet vereist:

/* 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.

Functies voor doorsturen

Een functie kan op voorhand worden gedeclareerd, dit is vergelijkbaar met specificaties in een C-headerbestand. Op die manier weet de compiler dat een functie later beschikbaar zal worden gesteld.

Zonder voorwaartse verklaringen MOET de functie worden aangegeven voordat deze de code wordt aangeroepen. De forward-aangifte bestaat uit de FUNCTION specificatie (functienaam, retourtype en parametergegevenstypen en volgorde). Als de forward-aangifte niet overeenkomt met de werkelijke functie, produceert de compiler fouten en kan de code niet worden uitgevoerd.

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.

Meerdere invoerparameters

/ * Hierdoor verschijnt een berichtvenster met de tekst "HELLO WORLD" * /

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

    RETURN c + " " + d.

END.

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

Meerdere retourafschriften (maar één retourwaarde)

Een functie kan meerdere retourinstructies hebben en ze kunnen in verschillende delen van de werkelijke functie worden geplaatst. Ze moeten echter allemaal hetzelfde gegevenstype retourneren.

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.

Een functie hoeft eigenlijk helemaal niets terug te geven. Dan is de retourwaarde? (onbekend). De compiler vangt dit niet op (maar uw collega's zullen het dus vermijden).

/* 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.

Uitgang en input-output parameters

Een functie kan slechts een enkele waarde retourneren, maar er is een manier om dit te omzeilen: de parameters zijn niet beperkt tot invoerparameters. U kunt de parameters INPUT , OUTPUT en INPUT-OUTPUT opgeven.

In tegenstelling tot INPUT parameters moet u OUTPUT of INPUT-OUTPUT opgeven voor de parameters.

Sommige coderingsconventies vinden dit misschien niet leuk, maar het kan wel.

/* 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 is een voorbeeld van een INPUT-OUTPUT parameter:

/* 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.

Herhaling

Zie recursie

Een functie kan zichzelf aanroepen en daardoor recidiveren.

FUNCTION factorial INTEGER (num AS INTEGER).

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

END FUNCTION.

DISPLAY factorial(5).

Met standaardinstellingen (opstartparameter) kan de voortgangssessie in dit voorbeeld geen grote aantallen verwerken. factorial(200) vult de stapel en veroorzaakt een fout.

Dynamische oproep van een functie

Met DYNAMIC-FUNCTION of het CALL -object kunt u functies dynamisch oproepen.

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.

Het CALL object is niet zo licht als de DYNAMIC-FUNCTION. Het kan worden gebruikt om verschillende dingen aan te roepen: functies, procedures, extern programma, Windows DLL-functies. Het kan ook methoden voor objecten oproepen en toegang krijgen tot afters / setters.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow