Argument evaluation strategies¶
Programming languages through the years have introduced several strategies to determine when and how to evaluate the argument of a routine call (by a routine, we mean a sequence of code that can be called with parameters like functions, procedures, methods, processes, coroutines, etc.). When a routine is called, its code is run with the parameters substituted by the actual arguments provided during the call. What differs is the exact nature of the substitution.
Call-by-value replaces the parameters in the routine body with the
value of the arguments. In other words, the expressions in arguments
are evaluated and this value is bound to the routine's parameters seen
as local variables of the routine. Thus, the callee cannot modify a value
referred to by the caller through its argument. This strategy is the most
common strategy, used in C
, Scheme
, etc.
Call-by-reference replaces the parameters by a reference to the
value of the arguments. The reference is handled transparently in the
routine body, where parameters are used like local variables. This
strategy allows a routine to alter a value refered by the caller. This
strategy is available in Pascal
, Fortran
, C++
(using a reference
for the type of the parameter), etc.
Call-by-name replaces the parameters in the routine body with the expressions given as actual arguments. This strategy is not very common in programming languages (Algol60 introduced it), but corresponds to the macro mechanism, with the exception of the time of evaluation (calling-by-name is interleaved with evaluation, while macros are textual substitutions done before any evaluation, which may lead to differences when a routine definition can be the product of the evaluation).
This categorization is blurred by the nature of the programming
languages: declarative (e.g. purely functional) or imperative, the type
system (if any; consider the C++
approach where arguments are passed by
values, but a reference type exists), the representation of values (if
all values are ‟boxed〞and implemented as pointers to boxes, the call by
value cannot be distinguished from the call by reference), and additional
mechanisms (like lazy
evaluation,
memoization or futures and
promises), etc.
Antescofo Evaluation Strategy¶
Antescofo implements call-by-value for functions, process and objects; and Antescofo macros implement textual substitution, which loosely corresponds to call-by-name.
However, nota bene that Antescofo data structures, i.e. tab,
map, nim and string, are implemented through a reference to an
underlying memory area. So, for instance, a tab may be shared between
the caller and the callee even if the call is by value. This ends up with
a behavior like call-by-reference for data structures. This behavior
"call-by-value where the value is a reference" is common: this is for
instance the behavior in C
, C++
or Java
.
The following example illustrates this point. Consider the following process and variable definitions:
@proc_def ::P($a, $b)
{
let $b := $b + 1
let $a[0] := $b
}
$t := [3, 1, 2]
$x := 10
_the corresponding data layout:_