Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser function laziness #3

Open
Derugon opened this issue Nov 21, 2024 · 1 comment
Open

Parser function laziness #3

Derugon opened this issue Nov 21, 2024 · 1 comment

Comments

@Derugon
Copy link
Contributor

Derugon commented Nov 21, 2024

Context

Parser functions from ParserFunctions are lazy with most of their parameters, they are expanded only when necessary. For example, {{#if: X | Y | Z }} (with X, Y, and Z some wikitext expressions) preprocesses the whole expression, but at first only the nodes from X are expanded, then Y is expanded if it is non-empty, otherwise Z is expanded. For template development with variables and cargo, this feature has at least two advantages:

  1. Reducing performance impact by not evaluating potentially costly expressions, and
  2. Providing a sort of control over side-effects, e.g. conditionally setting variables or storing data into a cargo table.

About ParserPower

Some parser functions from this extension are sometimes lazy in some of their parameters, and sometimes not, which can make functions trickier to use when relying on side-effects or evaluating performance-heavy expressions (e.g. cargo queries).

Below a few examples of parameters that are non-lazily expanded and that could be (technically) made lazily-expanded. This is only about the base parser functions, but the same goes for list handling functions.

{{#tokenif: value | token | pattern | default }}

If value is empty, default is expanded and token/pattern are not expanded.
Otherwise, both token/pattern and default are expanded, while default is not used afterwards.
For example:

{{#vardefine: x | no }}
{{#tokenif:  | @ | @ | {{#vardefine: x | yes }} }}
{{#var: x }}<!-- evaluates to "yes" -->

{{#vardefine: x | no }}
{{#tokenif: a | @ | @ | {{#vardefine: x | yes }} }}
{{#var: x }}<!-- evaluates to "yes", even though the default value is unused -->

{{#ueswitch: value | p1 = v1 | p2 = v2 }}

If value matches p1, then v1 is returned and neither p2 and v2 are expanded.
Otherwise, value is compared with the next parameter (p2), etc. But in this case, v1 is also expanded.
For example (also note that the last case is always evaluated):

{{#ueswitch: 1
 | 1= {{#vardefine: 1 | 1 }}
 | 2= {{#vardefine: 2 | 2 }}
 | 3= {{#vardefine: 3 | 3 }}
}}
{{#var: 1 }}{{#var: 2 }}{{#var: 3 }}<!-- evaluates to "13" -->

{{#ueswitch: 2
 | 1= {{#vardefine: 1 | 1 }}
 | 2= {{#vardefine: 2 | 2 }}
 | 3= {{#vardefine: 3 | 3 }}
}}
{{#var: 1 }}{{#var: 2 }}{{#var: 3 }}<!-- evaluates to "123" -->

This one is a little trickier, when parsing a case pi = vi:

  1. the whole expression pi = vi is expanded, then
  2. the string output is split around the 1st = (wich means comparing pi with value causes vi to be expanded).

The base #switch parser function works the other way around:

  1. pi = vi is split around the = without expanding neither pi or vi, then
  2. pi is expanded, then
  3. vi is expanded only if returned.

The question

Changing anything about laziness could break templates that rely on the fact that side effects will always be realized, whatever the parser function does.
So the first issue is: is it possible/feasible to change these behaviors / is the potential breakage acceptable?

@alex4401
Copy link
Member

Yup. Given built-in functions are lazy and the lack of laziness is not stated anywhere to be an explicit feature of ParserPower, I am OK with this behaviour being changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants