User-defined functions and macros can be used to extend the basic functionality provided by the built-in SALIERI functions and to adapt the SALIERI System and Language to specific needs.
User-defined functions are created using a statement of the form:
name := FUNC(n, body)
where name is a valid object name (the name of the functional object to be defined), n is an integer defining the number of parameters, and body a block defining the function body.
Functions have their own, local workspace; consequently, all objects which are created within a function body are local to that function. Also, objects of the global workspace cannot be modified or deleted within function bodies, however, they can be accessed.
The function parameters are accessed within function bodies using the special identifiers $1, $2, etc; all parameters are passed call-by-value, i.e., they are evaluated and stored in the local objects $i before the function body is executed. There is no automatic type-checking for function parameters; the only type restrictions for parameter values are imposed by their usage inside the function body. This way polymorphic functions can be easily realised. However, if type-checking is required, it can be done manually by using the type function.
Functions with a variable number of parameters can be realised by specifying the number of parameters as -1; in that case, $1 represents the whole parameter list within the function body.
To return a value from within a function, the statement return(val) is used, where val is an arbitrary SALIERI expression the value of which is returned as the function value; this also ends the execution of the function body immideately. The statement return() can be used to end the execution of a function body without returning a result.
To call a user-defined function, the syntax func(p_1,p_2,...)
is used, where func is the name of an arbitrary function object and p_i are arbitrary expressions the values of which are passed a as the actual function parameters. For functions which return a value, this statement is actually an expression, the type of which is determined by the respective result value; consequently, a function call like this can occur wherever an arbitrary expression of the respective type could occur, in particular on the right hand side of assigments and as function parameter values. Alternately, apply can be used to execute user-defined functions on given parameter values.
In SALIERI, functions are ordinary objects in that they can be copied, deleted and modified just like objects of any other type. Consequently, functions can be also passed as function parameter values or returned as function results. Also, functions can be defined within functions, when required. In doing so, one should keep in mind, that all objects created within function bodies, including local functions, exist only while the function body is being executed.
SALIERI does allow recursive function calls, i.e., a function can call itself from within its function body. When recursion is used, one has to make sure that no infinite recursions occur by carefully specifying the base cases. Also, depending on the actual implementation of SALIERI, the recursion depth might be very limited. WARNING: Too deep or infinite recursions may cause system crashes!
Macros are special functions which don't have a local workspace. Consequently, objects in the global workspace can be created, changed or deleted from within macro bodies. Macros are mainly used to initialise objects it the global workspace or to delete them; they should also be used for user-defined functions which do not require too many local objects whenever performance time has to be optimised since macro execution is slightly more efficient than function execution.
Macros are created using a statement of the form:
name := MACRO(n, body)
However, macros can have local objects; these have generally names of the form $id. In particular, macro parameter values are local objects and exist only during execution of the macro body.
Otherwise, macros are handled exactly like functions.
> f := FUNC(1, `res := $1+$1; write(res)')
> f([c1/4 d])
[c1/4 d1/4 c1/4 d1/4]
> f2 := FUNC(1, `return(retro($1))')
> s := f2([c1/4 d]
Result= [d1/4 c1/4]
> m := MACRO(1, `res := $1+$1; write(res)')
> f3 := FUNC(-1, `write(length($1)); return($1)')
See also: FUNC, MACRO, apply, return, function (Object Type), Macros, Blocks, Operators and Expressions.