# Evaluation methods In the [basics](scl.md#statements) section it has been noted that the order of the statements in the program provides no information for the interpreter and the output will not depend on this order. Rather the *dependencies* between variables and their parameters determine the execution order. ## Language interpreters and evaluation modes Currently, three different interpreters can be used to execute programs. These interpreters do not perform *eager evaluation*, i.e. do not evaluate parameters (such as function calls, expressions etc.) as soon as they are interpreted. Rather the evaluation is triggered only when a certain value is actually needed. Thus, the **order of evaluation** is neither the order of statements in the source code nor the order of interpretation. Another aspect of evaluation is the **time of evaluation** - during interpreter runs (let us call it *immediate*) and after the interpreter has finished (*deferred* evaluation). A third aspect is the **location of evaluation**: we make difference between *local* and *remote* evaluation. This is when we need additional computing resources that are not available locally (i.e. local HPC cluster with a batch system and a JupyterHub instance connected to it). The choice of interpreter determines the *evaluation mode* that is selected with `--mode | -m` command-line flags. The evaluation of parameters is essentially governed by the [evaluation policies](io.md#evaluation-policies) of [the evaluation modes](io.md#modes-of-evaluation) and by the ocurrence of `print` and `view` statements in the code. See next [section](io.md) for more details. ## Order of evaluation and short-circuiting Some built-in function calls and some expression types have the so-called **normal order evaluation**, i.e. they return values after only those input parameters are evaluated that are actually needed. This is sometimes referred to as *lazy evaluation*. Expressions including `if`, `or`, `and` evaluated in this way are known as *short-circuiting* expressions. In contrast, other parameters may be evaluated in **applicative order**, i.e. their evaluation begins only after all input parameters are evaluated. In instant (default) and deferred (`--mode deferred`) evaluation modes, all parameters are evaluated in normal order and the `or`, `and` and `if` expressions are short-circuiting. In workflow mode (`--mode workflow`) with no evaluation (default) or on-demand evaluation (`--on-demand --autorun`), the `or`, `and` and `if` expressions are short-circuiting when used within `print` statements. In all other workflow evaluation cases, i.e. on-demand evaluation of variables or with evaluate-all policy, the evaluation order is applicative and there is no short-cicuiting. Obviously, the mode and order of evaluation do not affect the outputs of the model but rather the behavior, i.e. the performance, location, resources used, time and costs of evaluation. ### Example In the following example, the input parameter `a` of the `if` function is not evaluated because only the second input parameter, that is a string literal, is only needed and evaluated. ``` a = 'abc' expr = true b = if(expr, 'xyz', a) print(b) ``` Swapping `'xyz'` and `a` (or changing the first input to `false`) will cause `a` to be evaluated but not the string literal `xyz`. Only evaluation in instant or deferred modes will have this behavior. In workflow mode, because the `if` function is in a variable statement, both `xyz` and `a` will be evaluated before the evaluation of the `if` function is started, no matter of the chosen evaluation policy. However, in workflow evaluation mode with on-demand (`--on-demand --autorun` flags) or no-evaluation (no flags) policy, the `if` function is short-circuiting: ``` a = 'abc' expr = true print(if(expr, 'xyz', a)) ``` In this mode it is also easy to check, that `a` is in fact not computed, with no-evaluation policy (omit `--autorun` flag), the statement `print(a)` will print `n.c.`.