Even if a custom function does not mutate state nor cause side-effects, it may still be volatile, i.e. it depends on the external environment and is not pure.
A perfect example is a function that gets the current time – obviously each run will return a different value!
The optimizer, when using
OptimizationLevel::Full, merrily assumes that all functions are non-volatile,
so when it finds constant arguments (or none) it eagerly executes the function call and replaces it with the result.
This causes the script to behave differently from the intended semantics.
Therefore, avoid using
OptimizationLevel::Full if volatile custom functions are involved.