LSPS documentation logo
LSPS Documentation
Functions

A function is a named closure: it has input parameters which are passed to the body of the function. The body comprises one or multiple expressions and return a value, which is the return value of the function.

Functions are declared and defined in a function definition file.

Note: PDS comes with two function editors, the text function editor and the visual function editor, which serve to create two different types of function definition files: When using the visual function editor, the output is an XML file with the declarations and definitions. The text function editor allows you to declare and define your functions as text. This section deals exclusively with the syntax of functions when they are defined as text. For more information on how the functions are declared and defined in PDS, refer to Functions in PDS guide.

To define a function use the following syntax:

/** <description> **/
<annotations>
<visibility> <returnType> <name> (<parameter1_type> <parameter1_name>, <parameter2_type> <parameter_name2>){
  <implementation>
}

Methods define their visibility:

  • private: accessible only from within the Module
  • public: accessible from the Module and from any importing Modules

Function parameters can be flagged as:

  • mandatory using the * symbol (unflagged parameters are optional)
  • variadic using the ... after the parameter type, for example, String... name

To define the default value of a parameter, use the <PARAM_TYPE> <PARAM_NAME> := <DEFAULT_PARAMETER_VALUE>

Functions Implemented by a Java Method

When implementing a function as a Java method, use the native keyword followed by the java method path that implements the function instead of the {<implementation>}, for example, native com.whitestein.lsps.example.myfunction;.

Note: The native implementation then receives the current context as its parameter.

Individual functions are declared and defined with the following syntax:

/** <description> **/
<annotations>
<visibility> <returnType> <name> (<parameter_type> <parameter_name>)
native <implementing_method>

Function Annotations

A function declaration can have the following annotations:

  • @SideEffect: on validation, the info notification about that the called function has a side effect is suppressed A function is considered to have side effects if one of the following is true:
    • The function modifies a variable outside of the function scope.
    • The function creates a shared record.
    • The function modifies a record field.
    • The function calls a function that causes a side effect.
  • @Deprecated: on validation, a notification about that the called function is deprecated is displayed
  • @Disabled: function is disabled (no calls can be performed)
  • @Status: modeling status of the function as @Status (<STATUS_NAME>)
  • @Meta: metadata of the function defined as @Meta(key1 -> value1, key2 -> value2, ...)
  • @ExtensionMethod: extension methods of existing Records; the first parameter is the Record you are extending

Calling Functions

Function calls are calls to function definitions which are special kinds of closures defined in a function definition: Function definitions are model elements which cannot be created directly in the Expression Language; however, you can call functions and use their return value in your expressions.

A function call follows the syntax

<FUNCTION_NAME>(<COMMA_SEPARATED_ARGUMENTS>)

or alternatively

<FUNCTION_NAME>(<PARAMETER_NAME_1> -> <ARGUMENT_1>, <PARAMETER_NAME_2> -> <ARGUMENT_2>)

The explicit definition of parameter names is useful if a parameter is not required and has a default value.

Example function call:

getModel("Delivery", 1.4)
//alternatively:
getModel(name -> "Delivery", version -> "1.4")

If a function uses type parameters, their types are inferred. However, you can define the types explicitly if required:

<FUNCTION> | <COMMA_SEPARATED_TYPES_PARAMETER_TYPES> | (<ARGUMENTS>)

The list of types in \<COMMA_SEPARATED_TYPES> is used in the same order as the type parameters are defined. Note that you need to define the types for all type parameters.

A function call is resolved into the function based on the call arguments: overloading is supported.

Call to a Standard Library function with the types of type parameters:

//collect has the E and T type parameters:
//E will be handled as Employee and T as Decimal:
sum(collect|Employee, Decimal|(e, {e -> e.salary}))