Template:If/doc: Difference between revisions

From Body Communication
en>Cedar101
m (→‎Performance considerations: <syntaxhighlight inline>)
 
(Created page with "{{Documentation subpage}} With this template the parser functions with names starting with "#if" can be used in a way such that they do not m:Help:N...")
Line 1: Line 1:
{{stack|{{Documentation subpage}}{{risky template|98320+}}}}
{{Documentation subpage}}
With this template the [[Help:parser function|parser functions]] of the [[mw:Help:Extension:ParserFunctions|ParserFunctions]] collection with names starting with "#if" can be used in a way such that they do not [[m:Help:Newlines_and_spaces#Stripping_on_expansion|strip spaces and newlines]] from the "then" and "else" part. Spaces still do not affect the outcome of the condition. Parameter 1 selects the if-type as "eq", "expr", "exist" or "error" (for #iferror), or empty "||" for a simple if-there (for #if). The template can be repeatedly nested 6 or 7 levels, one inside the other, because the outer-most is completed before running either the then/else inner levels.
With this template the [[Help:parser function|parser functions]] with names starting with "#if" can be used in a way such that they do not [[m:Help:Newlines_and_spaces#Trimming_on_expansion|strip spaces and newlines]] from the "then" and "else" part. Spaces still do not affect the outcome of the condition. Parameter 1 selects the if-type as "eq", "expr", "exist" or "error" (for #iferror), or empty "||" for a simple if-there (for #if). The template can be repeatedly nested 6 or 7 levels, one inside the other, because the outer-most is completed before running either the then/else inner levels.


This template can be substituted, when the expression or comparison will not change. Functionally, a lead-space character is stored, internally, as a simple blank character. Note, in many cases a null nowiki tag ("&lt;nowiki/>") could be used, without [[Template:If]], to allow a lead-space (such as "&lt;nowiki/>&nbsp;xx") anywhere, but the internal storage puts a 43-character marker for "&lt;nowiki/>" in string length. However, there is no extra expansion depth for a nowiki-tag, such as in trailing space, "zz&nbsp;&lt;nowiki/>".
This template can be substituted, when the expression or comparison will not change. Functionally, a lead-space character is stored, internally, as a simple blank character. Note, in many cases a null nowiki tag ("&lt;nowiki/>") could be used, without [[Template:If]], to allow a lead-space (such as "&lt;nowiki/>&nbsp;xx") anywhere, but the internal storage puts a 43-character marker for "&lt;nowiki/>" in string length. However, there is no extra expansion depth for a nowiki-tag, such as in trailing space, "zz&nbsp;&lt;nowiki/>".
Line 7: Line 7:
'''Where p is implemented in affirmation of the statement and q is implemented in negation of the statement'''
'''Where p is implemented in affirmation of the statement and q is implemented in negation of the statement'''


*<syntaxhighlight lang="text" inline>{{if||x| p | q }}</syntaxhighlight> gives "{{if||x| p | q }}". Notice the ''pair'' of vertical bars surrounding the empty first parameter.
*<nowiki>{{if||x| p | q }}</nowiki> gives "{{if||x| p | q }}". Notice the ''pair'' of vertical bars surrounding the empty first parameter.


*<syntaxhighlight lang="text" inline>{{if|expr|2<3| p | q }}</syntaxhighlight> gives " p "
*<nowiki>{{if|expr|2<3| p | q }}</nowiki> gives " p "
*<syntaxhighlight lang="text" inline>{{if|eq| u |u| p | q }}</syntaxhighlight> gives "{{if|eq| u |u| p | q }}"
*<nowiki>{{if|eq| u |u| p | q }}</nowiki> gives "{{if|eq| u |u| p | q }}"
*<syntaxhighlight lang="text" inline>{{if|exist| Help:Link | p | q }}</syntaxhighlight> gives "{{if|exist| Help:Link | p | q }}"
*<nowiki>{{if|exist| Help:Link | p | q }}</nowiki> gives "{{if|exist| Help:Link | p | q }}"
*<syntaxhighlight lang="text" inline>{{if|error|{{#expr:x}}| p | q }}</syntaxhighlight> gives "{{if|error|{{#expr:x}}| p | q }}"
*<nowiki>{{if|error|{{#expr:x}}| p | q }}</nowiki> gives "{{if|error|{{#expr:x}}| p | q }}"


Compare:
Compare:
*<syntaxhighlight lang="text" inline>{{#if:x| p | q }}</syntaxhighlight> gives "{{#if:x| p | q }}"
*<nowiki>{{#if:x| p | q }}</nowiki> gives "{{#if:x| p | q }}"
*<syntaxhighlight lang="text" inline>{{#ifexpr:2<3| p | q }}</syntaxhighlight> gives "{{#ifexpr:2<3| p | q }}"
*<nowiki>{{#ifexpr:2<3| p | q }}</nowiki> gives "{{#ifexpr:2<3| p | q }}"
*<syntaxhighlight lang="text" inline>{{#ifeq: u |u| p | q }}</syntaxhighlight> gives "{{#ifeq: u |u| p | q }}"
*<nowiki>{{#ifeq: u |u| p | q }}</nowiki> gives "{{#ifeq: u |u| p | q }}"
*<syntaxhighlight lang="text" inline>{{#ifexist: Help:Link | p | q }}</syntaxhighlight> gives "{{#ifexist: Help:Link | p | q }}"
*<nowiki>{{#ifexist: Help:Link | p | q }}</nowiki> gives "{{#ifexist: Help:Link | p | q }}"
*<syntaxhighlight lang="text" inline>{{#iferror:{{#expr:x}}| p | q }}</syntaxhighlight> gives "{{#iferror:{{#expr:x}}| p | q }}"
*<nowiki>{{#iferror:{{#expr:x}}| p | q }}</nowiki> gives "{{#iferror:{{#expr:x}}| p | q }}"


For example, with a template named ''Template:Template name'' containing the code <syntaxhighlight lang="text" inline>{{#ifeq: {{{parameter}}} |u| p | q }}</syntaxhighlight>, entering the code <syntaxhighlight lang="text" inline>{{{Template name|parameter=u}}}</syntaxhighlight> into an article gives "p", but <syntaxhighlight lang="text" inline>{{{Template name|parameter=v}}}</syntaxhighlight> gives "q".
For example, with a template named ''Template:Template name'' containing the code <nowiki>{{#ifeq: {{{parameter}}} |u| p | q }}</nowiki>, entering the code <nowiki>{{{Template name|parameter=u}}}</nowiki> into an article gives "p", but <nowiki>{{{Template name|parameter=v}}}</nowiki> gives "q".


The text of either the then-clause or else-clause is only processed and expanded when triggered. Hence, any templates in use are only expanded once the then-clause or else-clause is matched, otherwise they are skipped as merely paired braces, "&#123;&#123;" with "}}".
The text of either the then-clause or else-clause is only processed and expanded when triggered. Hence, any templates in use are only expanded once the then-clause or else-clause is matched, otherwise they are skipped as merely paired braces, "&#123;&#123;" with "}}".


===Indentation===
'''Indentation:''' If indenting the markup, care must be taken to avoid extra newlines when indenting "}}" on the next line. An extra bar pipe "|" can be added after the else-clause to complete that text, and allow "}}" to then be placed anywhere without adding a newline into the else-clause. For example:
If indenting the markup, care must be taken to avoid extra newlines when indenting "}}" on the next line. An extra bar pipe "|" can be added after the else-clause to complete that text, and allow "}}" to then be placed anywhere without adding a newline into the else-clause. For example:
:::* <nowiki>{{if|{{{1|}}}</nowiki><br>&nbsp; &nbsp; |then found parameter 1|else no parameter 1| &larr; ''extra'' "|" ''ends else-clause''<br>}}
:::* <syntaxhighlight lang="text">{{if|{{{1|}}}
    |then found parameter 1|else no parameter 1| extra "|" ends else-clause
}}</syntaxhighlight >
When the else-clause is indented to the next line, a newline (CR/LF) is added:
When the else-clause is indented to the next line, a newline (CR/LF) is added:
:::* <syntaxhighlight lang="text">{{if|{{{1|}}}
:::* <nowiki>{{if|{{{1|}}}</nowiki><br>&nbsp; &nbsp; |then found parameter 1 &larr; ''extra newline here''<br>&nbsp; &nbsp; |else noparameter 1|<br>}}
    |then found parameter 1 extra newline here
To indent the else-clause, split an [[HTML]]-form comment, as "&lt;!--" with next line as "--&gt;|else...". Unless each then-clause and else-clause is carefully tested, to watch for extra newlines, then the results are likely to cause broken lines, with extra line breaks for each newline. For that reason, a global edit with simple search-and-replace of "<code>{#if:</code>" to "<code>{if||</code>" is likely to leave newline problems, wherever the original markup was wrapped to indent either the else-clause or "}}" of each if-structure. Indenting the then-clause is not a problem.
    |else noparameter 1|
}}</syntaxhighlight>
To indent the else-clause, split an [[HTML]]-form comment, as "<code>&lt;!--</code>" with next line as "<code>--&gt;|else...</code>". Unless each then-clause and else-clause is carefully tested, to watch for extra newlines, then the results are likely to cause broken lines, with extra line breaks for each newline. For that reason, a global edit with simple search-and-replace of "<code>{#if:</code>" to "<code>{if||</code>" is likely to leave newline problems, wherever the original markup was wrapped to indent either the else-clause or "}}" of each if-structure. Indenting the then-clause is not a problem.


==Performance considerations==
==Performance considerations==
Because [[Template:If]] must prepare the parameters for <code>#if, #ifeq, #ifexpr,</code> (etc.) there is a slight overhead when using it. It has been timed to run at speeds of 290 instances per second, so 29 uses would take only 0.1&nbsp;s, a tenth of a second to run, to make 29 comparisons. Each nested use adds 5 levels to the template expansion depth, so 7 nested if-templates would use 35 levels (5*7) of the [[m:Help:Expansion_depth|41-level limit]].
Because [[Template:If]] must prepare the parameters for <code>#if, #ifeq, #ifexpr,</code> (etc.) there is a slight overhead when using it. It has been timed to run at speeds of 290 instances per second, so 29 uses would take only 0.1&nbsp;s, a tenth of a second to run, to make 29 comparisons. Each nested use adds 5 levels to the template expansion depth, so 7 nested if-templates would use 35 levels (5*7) of the [[m:Help:Expansion_depth|41-level limit]].


'''Using P-if syntax:''' A similar if-structure can be coded without '''Template:If''', by using the {{tlx|P1}} and {{tlx|P2}} templates in a "P-if" structure. [[Template:P1]] always returns parameter 1, and P2 returns the 2nd. So, a comparison of 4 versus 3 can be coded using P-if syntax form:
'''Using P-if syntax:''' A similar if-structure can be coded without '''Template:If''', by using the {P1} and {P2} templates in a "P-if" structure. [[Template:P1]] always returns parameter 1, and P2 returns the 2nd. So, a comparison of 4 versus 3 can be coded using P-if syntax form:
:: Example of <code>#ifexpr</code>: <syntaxhighlight lang="text" inline>"{{P{{#ifexpr: 4 > 3|1|2}}| then 4 greater| else 4 lower}}"</syntaxhighlight>
:: Example of <code>#ifexpr</code>: <nowiki>"{{P{{#ifexpr: 4 > 3|1|2}}| then 4 greater| else 4 lower}}"</nowiki>
:: Result for <code>#ifexpr</code>: &nbsp; "{{P{{#ifexpr: 4 > 3|1|2}}| then 4 greater| else 4 lower}}" &larr; ''the comparison invoked'' {<nowiki/>{P1}}.
:: Result for <code>#ifexpr</code>: &nbsp; "{{P{{#ifexpr: 4 > 3|1|2}}| then 4 greater| else 4 lower}}" &larr; ''the comparison invoked'' {<nowiki/>{P1}}.
The expansion depth of a P-if is only 4 levels deep, but nesting of the then-clause or else-clause might be more confusing than using nested levels of Template:if.
The expansion depth of a P-if is only 4 levels deep, but nesting of the then-clause or else-clause might be more confusing than using nested levels of Template:if.


:: Example of <code>#if</code>: <syntaxhighlight lang="text" inline>"{{P{{#if:{{{2|x}}}|1|2}}| then {2} set| else {2} empty}}"</syntaxhighlight>
:: Example of <code>#if</code>: <nowiki>"{{P{{#if:{{{2|x}}}|1|2}}| then {2} set| else {2} empty}}"</nowiki>
:: Result for <code>#if</code>: "{{P{{#if:{{{2|}}}|1|2}}| then {2} set| else {2} empty}}" &larr; ''the comparison invoked'' {<nowiki/>{P2}}.
:: Result for <code>#if</code>: "{{P{{#if:{{{2|}}}|1|2}}| then {2} set| else {2} empty}}" &larr; ''the comparison invoked'' {<nowiki/>{P2}}.


==See also==
==See also==
*[[m:Template:If]]
*[[m:Template:If]]
*[[Template:Ifnotempty]] - for simplicity and to reduce the limitations due to the expansion depth limit, this is a separate template corresponding to #if only.
 
*[[Template:Switch]], for a default result
<includeonly>
*[[Help:Conditional expressions]]
[[Category:Templates]]
<includeonly>{{Sandbox other||
</includeonly>
[[Category:If-then-else templates]]
}}</includeonly>

Revision as of 14:12, 7 August 2021

With this template the parser functions with names starting with "#if" can be used in a way such that they do not strip spaces and newlines from the "then" and "else" part. Spaces still do not affect the outcome of the condition. Parameter 1 selects the if-type as "eq", "expr", "exist" or "error" (for #iferror), or empty "||" for a simple if-there (for #if). The template can be repeatedly nested 6 or 7 levels, one inside the other, because the outer-most is completed before running either the then/else inner levels.

This template can be substituted, when the expression or comparison will not change. Functionally, a lead-space character is stored, internally, as a simple blank character. Note, in many cases a null nowiki tag ("<nowiki/>") could be used, without Template:If, to allow a lead-space (such as "<nowiki/> xx") anywhere, but the internal storage puts a 43-character marker for "<nowiki/>" in string length. However, there is no extra expansion depth for a nowiki-tag, such as in trailing space, "zz <nowiki/>".

Usage

Where p is implemented in affirmation of the statement and q is implemented in negation of the statement

  • {{if||x| p | q }} gives " p ". Notice the pair of vertical bars surrounding the empty first parameter.
  • {{if|expr|2<3| p | q }} gives " p "
  • {{if|eq| u |u| p | q }} gives " p "
  • {{if|exist| Help:Link | p | q }} gives " q "
  • {{if|error|{{#expr:x}}| p | q }} gives " p "

Compare:

  • {{#if:x| p | q }} gives "p"
  • {{#ifexpr:2<3| p | q }} gives "p"
  • {{#ifeq: u |u| p | q }} gives "p"
  • {{#ifexist: Help:Link | p | q }} gives "q"
  • {{#iferror:{{#expr:x}}| p | q }} gives "p"

For example, with a template named Template:Template name containing the code {{#ifeq: {{{parameter}}} |u| p | q }}, entering the code {{{Template name|parameter=u}}} into an article gives "p", but {{{Template name|parameter=v}}} gives "q".

The text of either the then-clause or else-clause is only processed and expanded when triggered. Hence, any templates in use are only expanded once the then-clause or else-clause is matched, otherwise they are skipped as merely paired braces, "{{" with "}}".

Indentation: If indenting the markup, care must be taken to avoid extra newlines when indenting "}}" on the next line. An extra bar pipe "|" can be added after the else-clause to complete that text, and allow "}}" to then be placed anywhere without adding a newline into the else-clause. For example:

  • {{if|{{{1|}}}
        |then found parameter 1|else no parameter 1| ← extra "|" ends else-clause
    }}

When the else-clause is indented to the next line, a newline (CR/LF) is added:

  • {{if|{{{1|}}}
        |then found parameter 1 ← extra newline here
        |else noparameter 1|
    }}

To indent the else-clause, split an HTML-form comment, as "<!--" with next line as "-->|else...". Unless each then-clause and else-clause is carefully tested, to watch for extra newlines, then the results are likely to cause broken lines, with extra line breaks for each newline. For that reason, a global edit with simple search-and-replace of "{#if:" to "{if||" is likely to leave newline problems, wherever the original markup was wrapped to indent either the else-clause or "}}" of each if-structure. Indenting the then-clause is not a problem.

Performance considerations

Because Template:If must prepare the parameters for #if, #ifeq, #ifexpr, (etc.) there is a slight overhead when using it. It has been timed to run at speeds of 290 instances per second, so 29 uses would take only 0.1 s, a tenth of a second to run, to make 29 comparisons. Each nested use adds 5 levels to the template expansion depth, so 7 nested if-templates would use 35 levels (5*7) of the 41-level limit.

Using P-if syntax: A similar if-structure can be coded without Template:If, by using the {P1} and {P2} templates in a "P-if" structure. Template:P1 always returns parameter 1, and P2 returns the 2nd. So, a comparison of 4 versus 3 can be coded using P-if syntax form:

Example of #ifexpr: "{{P{{#ifexpr: 4 > 3|1|2}}| then 4 greater| else 4 lower}}"
Result for #ifexpr:   " then 4 greater" ← the comparison invoked {{P1}}.

The expansion depth of a P-if is only 4 levels deep, but nesting of the then-clause or else-clause might be more confusing than using nested levels of Template:if.

Example of #if: "{{P{{#if:{{{2|x}}}|1|2}}| then {2} set| else {2} empty}}"
Result for #if: " else {2} empty" ← the comparison invoked {{P2}}.

See also