|
|
|
|
|
- Principle
- Declaring and calling internal procedures
- Example
- Characteristics of internal procedures
- Use in callback
- Internal Procedure parameter
- Access to the variables from an internal procedure
- Nesting internal procedures
- Sibling internal procedures
- Recursive calls
- Named parameters
- Dynamic compilation
- Internal procedure and extension attributes
- Special case: Using internal procedures with asynchronous functions
- Limitations
Several features require a procedure called once or several times via a WLanguage function ("Callback"). For example, this is the case for the following functions: fListFile, TreeListItem, AlbumPicker in iOS, etc. A procedure must be created for these functions but several drawbacks appear: - Loss of code locality: The final algorithm cannot be entirely displayed. Several backs and forths must be performed between the calling code and the WLanguage procedure.
- Difficulty to share information wiht the WLanguage procedure: In most cases, global variables must be used (to pass parameters to the callback or to retrieve the results).
In this case, the internal procedures are used to simplify the writing of callback features and to fix the problems caused when using a standard procedure. Declaring and calling internal procedures An internal procedure is declared in the code of an existing process (process associated with a control, window procedure, global procedure or class method, ...). The syntax is as follows: INTERNAL PROCEDURE <Procedure name>() <Procedure code> END Remarks: - The internal procedures must be declared in the process where they are used.
- The assisted input is enabled for the parameters: a tooltip specifying the expected parameter type is displayed when typing the call to the internal procedure.
- The code of process found before and after the declaration code of internal procedure is run in sequence: the code of internal procedure is not run.
Example:
// Code before the internal procedure: This code is run. INTERNAL PROCEDURE MyInternalProcedure() // Code of the internal procedure. // This code is not run. END // Code after the internal procedure: This code is run.
- An internal procedure can be directly called by its name, like any standard procedure. This call can be placed before or after the declaration of internal procedure.
Example:
// Call placed before MyInternalProcedure() Â // Declare the internal procedure INTERNAL PROCEDURE MyInternalProcedure() // Code of the internal procedure run during the call to MyInternalProcedure() END Â // Call placed after MyInternalProcedure()
This allows you to get a code that is easy to read. - The exceptions triggered by the internal procedures can be processed outside the internal procedure.
Characteristics of internal procedures Use in callback The internal procedure can be used in a WLanguage functions that expects a WLanguage procedure as parameter (like fListFile, TreeListItem, ...). Caution: In this case, the parameter corresponding to the name of internal procedure must directly correspond to the name of internal procedure (the procedure name must not be enclosed in quotes). Not to do: // List the "children" of the "Desserts" node in the "TREE_TVRecipe" TreeView Res = TreeListItem(TREE_TVRecipe, "Recipes" + TAB + "Desserts", "ExpandAll") Â INTERNAL PROCEDURE ExpandAll(TREE_TVRecipe, ChildPath, ChildFound, Level, Pointer) ... END
Do: // List the "children" of the "Desserts" node in the "TREE_TVRecipe" TreeView Res = TreeListItem(TREE_TVRecipe, "Recipes" + TAB + "Desserts", ExpandAll) Â INTERNAL PROCEDURE ExpandAll(TREE_TVRecipe, ChildPath, ChildFound, Level, Pointer) ... END
Internal Procedure parameter The internal procedure can be used as parameter in a procedure. In this case, the parameter type will be "Procedure". Example: // Declare the internal procedure INTERNAL PROCEDURE MyInternalProcedure() // code run during the call to the procedure passed as parameter END Â MyOtherProcedure(MyInternalProcedure)
PROCEDURE MyOtherProcedure(p is procedure) Â p()
Access to the variables from an internal procedure The variables declared in the same process as the declaration of internal procedure can be called in the internal procedure. There is no need to use global variables anymore. This concept is called "Closure". Example: sElementList is string sSeparator is string = CR TreeListItem(TREE_TreeeViewControl, "", MyInternalProcedure) Â INTERNAL PROCEDURE MyInternalProcedure(TreeViewName, Branch) sElementList += [sSeparator] + Branch END
Nesting internal procedures The internal procedures can be nested. Each internal procedure can access the variables of procedures that include it. Example: ExternalVariable is int Trace(ExternalVariable) MyInternalProcedure1() INTERNAL PROCEDURE MyInternalProcedure1() InternalVariable1 is int Trace(ExternalVariable + InternalVariable1) MyInternalProcedure2() INTERNAL PROCEDURE MyInternalProcedure2() InternalVariable2 is int Trace(ExternalVariable + InternalVariable1 + InternalVariable2) END END
Sibling internal procedures Two internal procedures found in the same procedure can be called between themselves (sibling internal procedures). Example: INTERNAL PROCEDURE MyMainProcedure() Â INTERNAL PROCEDURE MyInternalProcedure1() ... END Â INTERNAL PROCEDURE MyInternalProcedure2() ... // Call the sibling procedure MyInternalProcedure1() END END
Recursive calls An internal procedure can be called itself in recursive way. Named parameters If an internal procedure includes parameters with default values, you have the ability to call the internal procedure by naming its parameters. Two syntaxes are possible: - Single-line named parameters,
- Multiline named parameters.
Dynamic compilation You can use an internal procedure in a dynamically compiled code (with Compile, for example). Example: lsCode is string = [ // Code compiled dynamically sElementList is string sSeparator is string = CR TreeListItem(TREE_TreeeViewControl, "", MyInternalProcedure)  INTERNAL PROCEDURE MyInternalProcedure(TreeViewName, Branch) sElementList += [sSeparator] + Branch END  ]  lsResult is string  lsResult = Compile("MyProc",lsCode)
Internal procedure and extension attributes extension attributes can be used with internal procedures. For example, a single process can run an internal procedure in a secondary thread, then call a second procedure in the main thread to refresh the interface. Example: // Code of a button for example ... AsynchronousExecution() Â INTERNAL PROCEDURE AsynchronousExecution() <thread> Â // Here, process run in the background // in a secondary thread (no access to the interface) ThreadPause(5s) Â // Process completed, call process of main thread again // therefore allowed to refresh the interface AfterAsynchronousExecution() END Â INTERNAL PROCEDURE AfterAsynchronousExecution() <main thread> Trace("Completed ...") END
Special case: Using internal procedures with asynchronous functions The internal procedures can be used as "Callback" for asynchronous functions. CAUTION: In this case, the code after the call to the function that uses an asynchronous WLanguage procedure will be execute BEFORE the code of internal procedure. Example: In this WINDEV Mobile example, the code after AlbumPicker will be executed BEFORE the internal procedure. The internal procedure will be called when the picker is validated by the user. AlbumPicker(albumImage, PhotoSelection) INTERNAL PROCEDURE PhotoSelection(sImagePath) IMG_ImageControl = sImagePath END // Code run after the AlbumPicker function but // BEFORE the code of internal procedure.
- An internal procedure cannot be named like the procedures that contain it.
- Two internal procedures of same level cannot have the same name, even if they are declared in different code blocks (IF THEN ELSE, ...).
- The internal procedures are not available in dynamic compilation.
- The execution of an internal procedure cannot be automated.
- The automatic management of errors is not available for the internal procedures.
This page is also available for…
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|