Skip to content

When do we evaluate the local variables? #299

Closed
@mihnita

Description

@mihnita

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"

Metadata

Metadata

Assignees

No one assigned

    Labels

    blocker-candidateThe submitter thinks this might be a block for the next release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions