Sök…


Introduktion

En användardefinierad funktion i Progress ABL är en återanvändbar programmodul.

Anmärkningar

  • En funktion måste deklareras i "huvud" -förfarandet. Det kan inte deklareras i en procedur eller i en annan funktion.
  • En pågående funktion ABL är inte en "förstklassig medborgare" till skillnad från i programmeringsspråk som Haskell eller Javascript. Du kan inte passera en funktion som en ingångs- eller utgångsparameter. Du kan dock ställa in dem dynamiskt med hjälp av DYNAMIC-FUNCTION eller CALL objektet.
  • Att ringa funktioner i dina frågor kan leda till dålig prestanda eftersom indexmatchning kommer att skada. Försök att tilldela värdet av funktionen till en variabel och använda den variabeln i WHERE -clause istället.

Enkel 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").

Delar av syntaxen krävs faktiskt inte:

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

Framåt deklarera funktioner

En funktion kan förklaras framåt, detta liknar specifikationerna i en C-huvudfil. På så sätt vet kompilatorn att en funktion kommer att göras tillgänglig senare.

Utan framåtdeklarationer MÅSTE funktionen deklareras innan den anropas i koden. Framåtdeklarationen består av FUNCTION specifikationen (funktionens namn, returtyp och parameterdatatyper och ordning). Om framåtdeklarationen inte matchar den faktiska funktionen kommer kompilatorn att producera fel och koden misslyckas med att köras.

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.

Flera ingångsparametrar

/ * Detta kommer att spruta en meddelanderuta som säger "HELLO WORLD" * /

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

    RETURN c + " " + d.

END.

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

Flera avkastningsuppdrag (men ett enda avkastningsvärde)

En funktion kan ha flera returrätt och de kan placeras i olika delar av den faktiska funktionen. De behöver dock alla returnera samma datatyp.

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.

En funktion behöver faktiskt inte returnera någonting alls. Då kommer det att returnera värdet? (okänd). Kompilatorn kommer inte att fånga detta (men dina kollegor kommer så att undvika det).

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

Parametrar för utgång och ingång / utgång

En funktion kan bara returnera ett enda värde men det finns ett sätt att: parametrarna är inte begränsade till ingångsparametrar. Du kan deklarera INPUT OUTPUT , OUTPUT och INPUT-OUTPUT .

Till skillnad från INPUT parametrar måste du ange OUTPUT eller INPUT-OUTPUT före parametrarna.

Vissa kodningskonventioner kanske inte gillar detta men det kan göras.

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

Här är ett exempel på en 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.

Rekursion

Se rekursion

En funktion kan kalla sig själv och därmed återanvända.

FUNCTION factorial INTEGER (num AS INTEGER).

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

END FUNCTION.

DISPLAY factorial(5).

Med standardinställningar (startparameter) kan Progress-sessionen inte hantera mycket stora siffror i det här exemplet. factorial(200) kommer att fylla bunten och höja ett fel.

Dynamiskt samtal för en funktion

Med DYNAMIC-FUNCTION eller CALL -objektet kan du dynamiskt ringa funktioner.

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.

CALL objektet är inte lika lätt som DYNAMIC-FUNCTION. Det kan användas för att kalla olika saker: funktioner, procedurer, externt program, Windows DLL-funktioner. Det kan också påkalla metoder på objekt och få tillgång till bokstäver / setare.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow