Description
It does not matter if we do the evaluation in one go or in two steps, at some point one needs to go from the arguments to the final result (parts, in format to parts, or string)
And part of that is evaluating the local variables.
When do we do it?
It is not simply an implementation detail, as the evaluation might trigger errors / exceptions.
So this decision would affect the timing of these kind of errors.
Example 1:
let $exp = {$expiration :date skeleton=abcdEfGhijklmnopqRSTUVwxyz}
This would fail, because the skeleton contains invalid characters.
But only the function knows what's valid and what's not.
So you will get an exception when you invoke the function.
One might say: you should validate earlier, using some regex from the registry, without invoking the function.
But we also support this:
let $exp = {$expiration :date skeleton=$realSkeleton}
And we only know $realSkeleton
at evaluation time (might even be another local variable?).
Option 1: when it is "defined"
Option 2: first time it is referred (lazy eval + memoization)
Option 3: implementation dependent.
In the ICU4J implementation I went with 2.
Some benefits for 2 (why I chose it):
Might waste time, because not all of them may be used by the selected pattern (if we have selectors).
And might prevent supporting some use cases.
For example:
let $exp = {$expirationDate :datetime skeleton=yMMMMd}
let $due = {$amount :number unit=currency precision=2 rounding=up currency=$curCode}
match {$expirationDate :isDefined}
when true {You are due {$due} by {$exp}.}
when * {You are due {$due}.}
As you can see $exp
is only used on the true
branch.
Even more, the evaluation of $exp
might even fail if expirationDate
is undefined (not passed as argument, or is null).
And the condition protects us from this.
Even if we ask that the functions never fail (is that a good idea? puts more restrictions on how one writes the functions).
option 1 means that we will evaluate $exp
even if branch *
is selected. These are wasted cycles.
Side effect: naming
Late evaluation makes "variable" a bit confusing.
In most programming languages variables are evaluated when assigned (the right-side is evaluated before assignment).
That is why in my proposals this was "macro" or "alias"