# Help:Conditional expressions

This help page is a how-to guide.It details processes or procedures of some aspect(s) of Wikipedia's norms and practices. It is not one of Wikipedia's policies or guidelines, and may reflect varying levels of consensus and vetting. |

This page describes how to use various parser functions to display different results based on detected conditions in a page or template.

Here is a quick summary of these functions in terms of how they treat their input (the function names are linked to more detailed descriptions of them found below on this page):

`#if`

checks the truth value of a string`#ifeq`

checks whether two strings or numbers are equal`#switch`

compares a string to a set of possible values`#expr`

evaluates a mathematical expression`#ifexpr`

evaluates a mathematical expression and acts on the truth value of the result`#iferror`

checks whether a string (often an expression inside of`#expr`

) triggers a parser error`#ifexist`

checks whether a page with a given title exists on the wiki (including image/media files)

For the use of these functions in tables, see Help:Conditional tables.

## Summary[edit]

The basic syntax (and use) of each function is as follows:

`{{#if:`

*test string*|*value if true*|*value if false*}}- (selects one of two values based on whether the test string is true or false)

`{{#ifeq:`

*string 1*|*string 2*|*value if equal*|*value if unequal*}}- (selects one of two values based on whether the two strings are equal—a numerical comparison is done whenever that is possible)

`{{#switch:`

*test string*|*case1*=*value for case 1*| ... |*default*}}- (chooses between multiple alternatives based on the value of the test string—basically equivalent to a chain of
`#ifeq`

tests, but*much*more efficient)

- (chooses between multiple alternatives based on the value of the test string—basically equivalent to a chain of
`{{#expr:`

*expression*}}- (evaluates a given expression; see Help:Calculation for details)

`{{#ifexpr:`

*expression*|*value if true*|*value if false*}}- (selects one of two values based on the truth value of an evaluated expression)

`{{#iferror:`

*test string*|*value if error*|*value if no error*}}- (selects one of two values based on whether the test string generates a parser error)

`{{#ifexist:`

*page title*|*value if exists*|*value if doesn't exist*}}- (selects one of two values depending on the existence of a page having the given title)

Note that "truth" is interpreted very differently by the string-based `#if`

function and the numerically oriented functions `#expr`

and `#ifexpr`

. A string is considered true if it contains at least one non-whitespace character (thus, for example, the `#if`

function interprets the strings "0" and "FALSE" as true values, not false). Any string containing only whitespace or no characters at all will be treated as false (thus `#if`

interprets " " and "", as well as undefined parameters, as false values). On the other hand, in the expressions evaluated by `#expr`

and `#ifexpr`

, Boolean operators like `and`

, `or`

, and `not`

interpret the numerical value 0 as false and any other number as true. In terms of output, Boolean operations return 1 for a true value and 0 for false (and these are treated as ordinary numbers by the numerical operators). Non-numerical strings (including most uses of empty strings and undefined parameters) will cause `#expr`

and `#ifexpr`

to report an error.

Also note that all leading and trailing whitespace within each of the parts of a parser function call gets stripped out, allowing the calls to be formatted with extra whitespace for better readability. For example:

```
{{#if: {{{xx|}}}
| parameter xx value is true
| parameter xx value is false
}}
```

Here, only the spaces in the strings "parameter xx value is true" and "parameter xx value is false" are significant. All other whitespace is ignored. Thus, the construct above is equivalent to the following call:

```
{{#if:{{{xx|}}}|parameter xx value is true|parameter xx value is false}}
```

In any part of a parser function call where a string is expected, one can use a literal string, a template call, a parser function call, or some other magic word.

## Using `#if`

[edit]

*See also: the*`{{if}}`

template

The `#if`

function selects one of two alternatives based on the truth value of a test string.

`{{#if:`

*test string*|*value if true*|*value if false*}}

As explained above, a string is considered true if it contains at least one non-whitespace character. Any string containing only whitespace or no characters at all will be treated as false.

Undefined parameter values are tricky: if the first positional parameter was not defined in the template call, then `{{{1}}}`

will evaluate to the literal string "{{{1}}}" (i.e., the 7-character string containing three sets of curly braces around the number 1), which is a *true* value. (This problem exists for both named and positional parameters.) But `{{{1|}}}`

will evaluate to the empty string (a *false* value) because the vertical bar or pipe character, `"|"`

, immediately following the parameter name specifies a default value (here an empty string because there is nothing between the pipe and the first closing curly brace) as a "fallback" value to be used if the parameter is undefined.

This function can be used to check whether a parameter has been passed to a template with a true value.

Examples:

```
{{#if: {{{1|}}}
| first positional parameter has a true value
| first positional parameter has a false value (or no value)
}}
{{#if: {{{xx|}}}
| named parameter xx has a true value
| named parameter xx has a false value (or no value)
}}
{{#if: {{{xx|}}}{{{yy|}}}
| either xx or yy has a true value, or both are true
| both xx and yy have a false value (or no value)
}}
```

Testing whether both of two parameters are true requires a little more effort. For example:

```
{{#if: {{{xx|}}}
| {{#if: {{{yy|}}}
| both xx and yy have true values
| xx is true but not yy
}}
| both xx and yy are false
}}
```

Note that nesting `#if`

functions like this gets very resource-intensive very fast. On some wikis, even seven levels of nesting might exceed resource limits.

See the discussion of `#ifeq`

for how to detect whether a parameter has been defined regardless of whether its value is true or false.

## Using `#ifeq`

[edit]

*See also: the*`{{ifeq}}`

template

The `#ifeq`

function selects one of two alternatives based on whether two test strings are equal to each other.

`{{#ifeq:`

*string 1*|*string 2*|*value if equal*|*value if not equal*}}

If both strings are valid numerical values, they are compared as numbers, rather than as literal strings:

`{{#ifeq: 01 | 1 | equal | not equal }}`

→**equal**`{{#ifeq: x01 | x1 | equal | not equal }}`

→**not equal**`{{#ifeq: 2.000 | 002 | equal | not equal }}`

→**equal**`{{#ifeq: 2.5 | 2+.5 | equal | not equal }}`

→**not equal**(arithmetic!)`{{#ifeq: 2*10^3 | 2000 | equal | not equal }}`

→**not equal**(arithmetic!)`{{#ifeq: 2E3 | 2000 | equal | not equal }}`

→**equal**

As seen in the 4th and 5th examples, mathematical expressions are *not* evaluated. They are treated as regular strings. But `#expr`

can be used to evaluate such expressions.

`{{#ifeq: {{#expr:2*10^3}} | 2000 | equal | not equal }}`

→**equal**

String comparisons are case-sensitive:

`{{#ifeq: King | king | equal | not equal }}`

→**not equal**

For case-insensitive checking, use the `{{lc:}}`

or `{{uc:}}`

function to force the strings to all lower- or upper-case. This is most useful when dealing with parameter values:

`{{#ifeq: {{lc:King}} | king | equal | not equal }}`

→**equal**`{{#ifeq: {{lc: {{{position}}} }} | top | code if true | code if false }}`

In the second example, the values "top", "Top", and "TOP" will all result in successful matches.

This parser function can be used to detect whether a template parameter is defined, even if it has been set to a false value. For example, to check whether the first positional parameter has been passed to a template (note that the strings "`+`

" and "`-`

" can be any two different non-whitespace strings):

`{{#ifeq: {{{1|+}}} | {{{1|-}}} | 1 is defined | 1 is undefined }}`

To be specific, here's what this code generates when called in the following ways:

`{{`

→`template-name`}}**1 is undefined**`{{`

→`template-name`|}}**1 is defined**`{{`

→`template-name`|1=}}**1 is defined**`{{`

→`template-name`|1=foo}}**1 is defined**

See mw:Help:Extension:ParserFunctions##ifeq for more details, including possible counterintuitive results due to the way this function is implemented.

## Using `#switch`

[edit]

The `#switch`

function selects between multiple alternatives based on an input string.

`{{#switch:`

*test string*|*case1*=*value for case 1*| ... |*default value*}}

Equivalent to the switch statement found in some programming languages, it is a convenient way of dealing with multiple cases without having to chain lots of `#if`

functions together. However, note that performance suffers when there are more than 100 alternatives. Placing common values earlier in the list of cases can cause the function to execute significantly faster.

For each case, either side of the equals sign "`=`

" can be a simple string, a call to a parser function (including `#expr`

to evaulate expressions), or a template call. If any cases are not associated with a value (i.e., no equals sign is used), the next specified value will be used. This allows multiple cases to share the same value without having to specify that value repeatedly (as seen in the example below).

If no matching case is found, then the default value is used. This is usually specified last with no associated "*case*" value, as seen in the syntax summary above, but it can also be specified at any point after the test string if the construct `| #default = `

is used (see the second example below). If no default is specified in either way, then a null string will be returned when no cases match the input string.
*value*

This function in particular benefits from being set up in a multiline format.

```
{{#switch: {{{x|}}}
| 1 = one
| 2 = two
| 3 = three
| 4 = four
| 5
| 6
| 7 = in the range 5 to 7
| other
}}
```

Here, if the value of the template parameter `x`

is the string "1", then the output will be the string "one"; if "2", then "two"; and so forth. But for any of the values "5", "6" or "7", the output will be the string "in the range 5 to 7". For any other value, or a null value, it will return the string "other".

The following example is equivalent to the previous one:

```
{{#switch: {{{x|}}}
| #default = other
| 1 = one
| 2 = two
| 3 = three
| 4 = four
| 5|6|7 = in the range 5 to 7
}}
```

See Help:Switch parser function for a full description and more examples.

## Using `#expr`

[edit]

The `#expr`

function evaluates mathematical (including Boolean) expressions. While not itself a conditional function, it is often used inside of those functions, so it is briefly described here. See m:Help:Calculation for further details.

`{{#expr:`

*expression*}}

Unlike the `#if`

function, all values in the

evaluated by *expression*`#expr`

are assumed to be numerical. It does not work with arbitrary strings. For the purpose of its Boolean operations (e.g., `and`

, `or`

, and `not`

), false is represented by 0 and true by 1; these values are treated as regular numbers by the numerical operators. As input, the Boolean operators treat 0 as false and every other number as true. If any non-numerical strings are used, an error will result.

Examples:

`{{#expr: ( {{{1}}}+{{{xshift}}} - 6 ) * 18.4 }}`

`{{#expr: ln(7)^3 - abs(-0.344) + floor(5/3) round 3 }}`

`{{#expr: {{{n}}}>0 and {{{n}}}<1.0 }}`

Note that these examples assume that all parameters referred to are defined and have numerical values. If this is not the case, errors will occur. See `#iferror`

for one way to handle errors.

## Using `#ifexpr`

[edit]

The `#ifexpr`

function evaluates an expression in exactly the same way `#expr`

does (see the explanation of that function for details), but returns one of two possible values depending on the truth value of the result.

`{{#ifexpr:`

*expression*|*value if true*|*value if false*}}

Examples:

`{{#ifexpr: ( {{{1}}} + {{{2}}} ) * 2.63 > 45 | above 45 | not above 45 }}`

`{{#ifexpr: {{{1}}} > 0 and {{{1}}} < 1.0 or {{#ifeq:{{{decimal}}}|yes}} | is decimal | not decimal }}`

As explained above, for the purposes of this function, 0 is false and any other numerical value is true.

`{{#ifexpr: 0 | yes | no }}`

→**no**`{{#ifexpr: 1 | yes | no }}`

→**yes**`{{#ifexpr: 2 | yes | no }}`

→**yes**

An empty input expression evaluates to false.

`{{#ifexpr: | yes | no }}`

→**no**

But invalid input, including input containing non-numerical strings, will display an error message.

`{{#ifexpr: = | yes | no }}`

→**Expression error: Unexpected = operator**`{{#ifexpr: A=B | yes | no }}`

→**Expression error: Unrecognized word "a".**

Under normal circumstances, the function `#ifexpr`

is equivalent to using the following construct with `#ifeq`

and `#expr`

(note the reversal of the "true" and "false" output values, since we are comparing the input result to "0"):

`{{#ifeq: {{#expr:`

*expression*}} | 0 |*value if false*|*value if true*}}

But any error message generated by `#expr`

will be seen by `#ifeq`

as an ordinary string that is not equal to "0", and thus the

will be output.
*value if true*

`{{#ifeq: {{#expr: = }} | 0 | yes | no }}`

→**no**

Either or both of the output values may be omitted (or left empty), in which case (assuming the "missing" branch of the construct is reached) no output results.

`{{#ifexpr: 1 > 0 | yes }}`

→**yes**`{{#ifexpr: 1 > 0 | | no }}`

→

Tip |

See mw:Help:Extension:ParserFunctions##ifexpr for more details, including possible counterintuitive results due to the way this function is implemented.

## Using `#iferror`

[edit]

The `#iferror`

function selects one of two alternatives depending on whether its input triggers an error.

`{{#iferror:`

*test string*|*value if error*|*value if correct*}}

The test string is typically a call to `#expr`

or some other parser function, but can be plain text or a template call, in which case an error would be triggered by any HTML object with `class="error"`

or any of various template errors such as loops and recursions, or some other "failsoft" parser error.

One or both of the return values can be omitted. If the

is omitted, the test string is returned if it is not erroneous. If the *value if correct*

is also omitted, an empty string is returned on an error:
*value if error*

`{{#iferror: {{#expr: 1 + 2 }} | error | correct }}`

→**correct**`{{#iferror: {{#expr: 1 + X }} | error | correct }}`

→**error**`{{#iferror: {{#expr: 1 + 2 }} | error }}`

→**3**`{{#iferror: {{#expr: 1 + X }} | error }}`

→**error**`{{#iferror: {{#expr: 1 + 2 }} }}`

→**3**`{{#iferror: {{#expr: 1 + X }} }}`

→`{{#iferror: {{#expr: . }} | error | correct }}`

→**correct**`{{#iferror: <strong class="error">a</strong> | error | correct }}`

→**error**

## Using `#ifexist`

[edit]

The `#ifexist`

function selects one of two alternatives depending on whether a page exists at the specified title.

`{{#ifexist:`

*page title*|*value if page exists*|*value if page doesn't exist*}}

The page can be in any namespace, so it can be an article or "content page", an image or other media file, a category, etc. The actual content of the page is irrelevant, so it may be empty or a redirect. Titles that would result in redlinks do not exist (and, as with redlinks, checking for the existence of a nonexistent page causes the title to appear on Special:WantedPages).

The checking is extremely fast, but has been limited to 500 instances per page because it is considered an "expensive parser function". (However, multiple checks of the *same* title on the same page do not count as multiple instances, because the results of the first check is cached and reused for the subsequent checks.)

## Checking for template parameters[edit]

A common idiom encountered in template coding is the "chain of fallback values", as seen in this example:

`{{{1|{{{url|{{{URL|}}}}}}}}}`

Here, if the first positional parameter is defined, then its value will be used. If it is undefined, then the parameter named `url`

will be checked and if it is defined, then its value will be used. If both the first positional parameter and `url`

are undefined, then the parameter named `URL`

is checked: if it is defined, its value is used; if not, then the empty string will be used.

The problem is, this construct tends to be interpreted as being equivalent to:

`{{#if: {{{1|}}} | {{{1}}} | {{#if: {{{url|}}} | {{{url}}} | {{#if: {{{URL|}}} | {{{URL}}} }} }} }}`

and it is **not**. The difference is that the first construct, using default values, depends on the *definedness* of the parameters, whereas the second construct, using `#if`

functions, depends on the *truth value* of the parameters. These are two very different things.

If any of the parameters in the chain of fallback values (in the first construct) have been set to an empty value (or only whitespace) in the template call, then that empty value will be used instead of "falling back" to the next parameter in the chain. So, for example, if the template is called in either of these two ways:

`{{template-name||url=https://example.com/}}`

`{{template-name|url=https://example.com/|}}`

The first positional parameter *has* been defined: its value is the empty string. Thus, the value of `url`

is irrelevant. The template never "gets to" that value.

Similarly, if the template is called in this way:

`{{template-name|url=|URL=https://example.com/}}`

The empty value of `url`

will be used instead of the value of `URL`

.

These examples might seem a bit contrived, since they rely on the template being called in "the wrong way". But it is surprisingly easy to run across cases where these problems occur with perfectly reasonable template calls (especially if there is a "hierarchy" of templates, where one template calls another, passing on the values of its parameters to the parameters of the "lower-level" template—in such cases, one will often end up with defined-but-empty parameter values).

Because of issues like this, template coders sometimes find themselves needing to distinguish between different combinations of three states: defined-and-non-blank, defined-and-blank, and undefined. This can be done in the following ways (the first positional parameter is used here, but named parameters work the same way).

- Defined-and-non-blank vs. undefined or defined-and-blank
`{{#if: {{{1|}}} | 1 is defined and contains non-whitespace | 1 is undefined, empty, or contains only whitespace }}`

- Defined (whether non-blank or blank) vs. undefined
- The following are equivalent alternatives:
`{{#ifeq: {{{1|+}}} | {{{1|-}}} | 1 is defined (and possibly empty or only-whitespace) | 1 is undefined }}`

`{{#ifeq: {{{1|/}}}{{{1|}}} | / | 1 is undefined | 1 is defined (and possibly empty or only-whitespace) }}`

`{{#if: {{#if: {{{1|/}}} | {{{1|}}} | / }} | 1 is defined (and possibly empty or only-whitespace) | 1 is undefined }}`

Note that the `+`

and `-`

characters can be any two different non-whitespace characters. Also, if you just want to use the value of the parameter when it's defined and some other value when it's undefined, you can use the simpler "fallback" construct:

`{{{1|`

*some other value*}}}

- Defined-and-non-blank vs. defined-and-blank vs. undefined
- The following are equivalent alternatives:
`{{#ifeq: {{{1|+}}} | {{{1|-}}} | 1 is defined {{#if: {{{1|}}} | and non-blank | and blank }} | 1 undefined }}`

`{{#if: {{{1|/}}} | {{#if:{{{1|}}} | 1 is defined and non-blank | 1 is undefined }} | 1 is defined and blank }}`

If you don't care about the undefined case, you can remove the "`|1 undefined`

" in both examples.

## Variadic templates[edit]

Wikitext syntax does not allow natively to create truly variadic templates, but only pseudo-variadic ones, that check the incoming parameters one by one until a certain fixed amount. It is possible to break this limitation however by using dedicated modules. For simple cases, {{#invoke:separated entries|main}} allows to expand all sequential parameters blindly and has the ability to set custom delimiters. For more complex cases, {{#invoke:params}} allows to count, list, map, filter and propagate all incoming parameters without knowing their number in advance.

## See also[edit]

- Help:Conditional tables
- mw:Help:Extension:ParserFunctions, a longer and more technical help page at MediaWiki.org
- Conditional (computer programming)
- Relational operator
- Help:Template and Wikipedia:Template sandbox and test cases
- m:Help:Advanced templates
- Category:If-then-else templates