Call
Synopsis
Functions and constructors can be called or invoked in a uniform style.
Syntax
Call with positional parameters:
Name ( Exp₁, Exp₂, ... )
Call with keyword parameters:
Name (Name₁ = Exp₁, Name₂ = Exp₂, ...)
Call with both positional and keyword parameters:
Name (Exp₁, Exp₂, ..., Name₁ = Exp₁, Name₂ = Exp₂, ...)
Types
Exp₁ | Exp₂ | ... | Name ( Exp₁, Exp₂, ... ) |
---|---|---|---|
T₁ | T₂ | ... | Determined by Name, Tᵢ and function declarations |
Description
For the purpose of calling a function or a constructor, we make no distinction between these two concepts. A constructor is a function that constructs an application of an algebraic data-type constructor definition, so it has no body, but it is a function which can be called.
First, the actual parameter expressions Expᵢ are evaluated resulting in values Vᵢ. Based on Name and the argument types Tᵢ, the identity of the function to be called is determined.
The values Vᵢ are bound to the formal parameter names of the declared functions and the function body is executed. The value returned by the function is used as value of the function call.
For the keyword parameters a similar evaluation produces values for each expression and those values are bound to the respective names.
- The order of keyword parameters is irrelevant in the call syntax, as opposed to the order of the positional parameters.
- Notably, values are also bound for the keyword parameters which are not listed in the call site. For those values, default expressions are evaluation which are retrieved from the Function signature.
- For Functions those default parameters are computed and bound at the time of calling the function
- For Algebraic Data Type constructors, the missing default parameters are computed, lazily, at the moment of FieldSelection.
For more information:
- see Function for more details about function declarations.
- see Algebraic Data Type for more details about constructor declarations.
In case of function overloading, where there a more definitions of the same function (the same name and argument arity), there is a selection process called "dynamic dispatch". The functions are tried in arbitrary order, and if their signature matches, and their body does not Fail, then the return value of that function is used. Otherwise, the next function alternative is tried until a succesful alternative is found. If the match of the signature is non-unitary, it involves backtracking, then a single function may be tried many times.
If the name of the function in the call is
Examples
First declare a function square
with argument n that returns n^2:
rascal>int square(int n) { return n * n; }
int (int): function(|prompt:///|(0,35,<1,0>,<1,35>))
Next call square
. This results in the following steps:
- Based on the name
square
and the int argument 12 we identify the function to be called (= the functionsquare
we just defined). - Compute the value of the actual parameter (= 12).
- Bind the formal parameter
n
to the actual value 12. - Execute the body of
square
. - The return value of square is the vale of the call:
rascal>square(12);
int: 144
Benefits
- calls with positional parameters are the classical way of function invocation in Mathematics and Computer Science
- calls with keyword parameters provide readability at the call site and we do not have to remember the invocation order
- calls with keyword parameters are always bound by defaults, so there is never a
null
reference