User:BrandonXLF/Help:Infinite parameters
![]() | This help page is a how-to guide. It explains concepts or processes used by the Wikipedia community. It is not one of Wikipedia's policies or guidelines, and may reflect varying levels of consensus. |
Support for infinite parameters allows a template to accept a unlimited number of parameters. These can either be unnamed parameters (|1=
, |2=
, |3=
, etc.) or named (|item1=
, |item2=
, |item3=
, etc.). This is similar in concept to a variadic function. As wikitext does not have built-in support for infinite parameters, templates that support infinite parameters make use of Lua modules.
Custom modules
[edit]One way add support for infinite parameters to a template is to write a custom Lua modules that implements the template. This is done by modules like Module:Jct, Module:Infobox, Module:List, and Module:Template link general. There are several strategies for supporting infinite parameters in Lua, some of which are demonstrated below.
Sequential parameters
[edit]ipairs
is a built in function that can be used to iterate over sequential numbered (unnamed) parameters. It works by reading non-nil
values starting with the key 1
. It is used in conjunction with a for loop. For example, if a module, __MODULE__
, existed with the code below:
local p = {}
function p.main(frame)
local args = frame:getParent().args
local out = ''
for i, v in ipairs(args) do
if out then out = out .. ', ' end
out = out .. i .. ' is ' .. v
end
return out
end
return p
Then, when a template with {{#invoke:__MODULE__|main}}
is called with {{__TEMPLATE__|A|B|C}}
, the output 1 is A, 2 is B, 3 is C
would be produced.
Using a while loop works great when there is a prefix in front of the parameter number as ipairs will not work in those situations. The definition of i
can also be set to start with a different number besides 1
. For example, if a module, __MODULE__
, existed with the code below:
local p = {}
function p.main(frame)
local args = frame:getParent().args
local out = ''
local i = 1
while args['prefix' .. i] do
if out then out = out .. ', ' end
out = out .. 'prefix' .. i .. ' is ' .. v
i = i + 1
end
return out
end
return p
Then, when a template with {{#invoke:__MODULE__|main}}
is called with {{__TEMPLATE__|prefix1=A|prefix2=B|prefix3=c}}
, the output 1 is A, 2 is B, 3 is C
would be produced.
Non-sequential parameters
[edit]Using TableTools.sparseIpairs
[edit]
There are several templates like {{Infobox}} that need to support non-sequential parameters. This is commonly achieved with Module:TableTools, which contains functions like sparseIpairs
for working with sparse arrays. The example below can skip over nil
values, whereas the ipairs
example stops at the first nil
value. For example, if a module, __MODULE__
, existed with the code below:
local TableTools = require('Module:TableTools')
local p = {}
function p.main(frame)
local args = frame:getParent().args
local out = ''
for i, v in TableTools.sparseIpairs(args) do
if out then out = out .. ', ' end
out = out .. i .. ' is ' .. v
end
return out
end
return p
Then, when a a template with {{#invoke:__MODULE__|main}}
is called with {{__TEMPLATE__|A|B|100=C}}
, the output 1 is A, 2 is B, 100 is C
would be produced despite parameters 3
to 99
not being defined.
Using pairs
and table.sort
[edit]
When an existing method like those in Module:TableTools don't work (due to having prefixed parameter names or other issues), iterating over all arguments with pairs
, recording the number of the ones you're interested in, sorting the array of said numbers with table.sort
, and then using ipairs
to go over that sorted array is a common method as shown below. For example, if a module, __MODULE__
, existed with the code below:
local p = {}
function p.main(frame)
local args = frame:getParent().args
local out = ''
-- Traverse all arguments and record item argument numbers
local argNums = {}
for k, _ in pairs(args) do
local num = tostring(k):match('^item([1-9]%d*)$')
if num then table.insert(argNums, tonumber(num)) end
end
table.sort(argNums) -- Sort the found argument numbers
for _, num in ipairs(argNums) do
if out then out = out .. ', ' end
out = out .. 'item' .. num .. ' is ' .. args['item' .. num]
end
return out
end
return p
Then, when a template with {{#invoke:__MODULE__|main}}
is called with {{__TEMPLATE__|item1=A|item2=B|item100=C}}
, the output item1 is A, item2 is B, item100 is C
would be produced despite parameters item3
to item99
not being defined.
Using metamodules
[edit]If you'd like to avoid writing an entire Lua module, there are metamodules that exist to help aid in adding infinite parameter support for functions. Examples on how to use some of these metamodules are shown below.
Arbitrary wikitext
[edit]These modules work by taking wikitext in <nowiki>...</nowiki>
and expanding it while passing it the appropriate parameters. Examples of using the various modules that support arbitrary wikitext are shown below.
Unnamed parameters
[edit]
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:Map params|map|sep=<br>|<nowiki><code>{{{i}}}</code> is {{2x|{{{1}}}|, }}</nowiki>}}
Then,
{{__TEMPLATE__|A|B|C}}
|
would produce | 1 is A, A2 is B, B3 is C, C
|
If the template __TEMPLATE__
is defined with the code below:
{{#if:{{{1|}}}|<code>1</code> is {{2x|{{{1}}}|, }}}}{{#invoke:ArgRest|main|<nowiki><br><code>?</code> is {{2x|{{{2}}}|, }}</nowiki>|2}}
Then,
{{__TEMPLATE__|A|B|C}}
|
would produce |
|
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:Params|setting|i|<br>|sequential|for_each|<code>$#</code> is {{2x|$@|, }}}}
Then,
{{__TEMPLATE__|A|B|C}}
|
would produce | 1 is A, A2 is B, B3 is C, C
|
Note that this example processes the wikitext before the arguments are substituted. So, the call to {{2x}} actually outputs $@, $@
rather than A, A
etc.
Named parameters
[edit]
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:Map params|map|prefix=item|extra=extra(i)|sep=<br>|<nowiki><code>item{{{i}}}</code> is {{{item}}}{{#if:{{{extra|}}}|{{sp}}and <code>extra{{{i}}}</code> is {{{extra}}}}}</nowiki>}}
Then,
{{__TEMPLATE__
| item1 = A
| extra1 = Apple
| item2 = B
| extra2 = Orange
| item3 = C
}}
|
would produce | item1 is A and extra1 is Appleitem2 is B and extra2 is Orangeitem3 is C
|
If the template __TEMPLATE__
is defined with the code below:
{{#if:{{{item1|}}}|<code>item1</code> is {{{item1}}}{{#if:{{{extra1|}}}|{{sp}}and <code>extra1</code> is {{{extra1}}}}}}}{{#invoke:ArgRest|main|<nowiki><br><code>item?</code> is {{{item2}}}{{#if:{{{extra2|}}}|{{sp}}and <code>extra?</code> is {{{extra2}}}}}</nowiki>|item2}}
Then,
{{__TEMPLATE__
| item1 = A
| extra1 = Apple
| item2 = B
| extra2 = Orange
| item3 = C
}}
|
would produce | item1 is A and extra1 is Appleitem? is B and extra? is Orangeitem? is C
|
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:params|setting|i|<br>|all_sorted|call_for_each_group|__CHILD_TEMPLATE__}}
And the template __CHILD_TEMPLATE__
is defined with the code below:
<code>item?</code> is {{{item}}}{{#if:{{{extra|}}}|{{sp}} and <code>extra?</code> is {{{extra}}}}}
Then,
{{__TEMPLATE__
| item1 = A
| extra1 = Apple
| item2 = B
| extra2 = Orange
| item3 = C
}}
|
would produce | item? is A and extra? is Appleitem? is B and extra? is Orangeitem? is C
|
Unlike the other examples, this one uses a child template. This allows the wikitext to be written outside of <nowiki>...</nowiki>
tags, but it separates the code across multiple templates.
Fixed output format
[edit]These modules are more specialized and limited than the ones above. Examples for using them are below.
Unnamed parameters
[edit]
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:Separated entries|main|separator= also |conjunction= and finally }}
Then,
{{__TEMPLATE__|A|B|C}}
|
would produce | A also B and finally C |
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:Enumerate|main}}
Then,
{{__TEMPLATE__|A|B|C}}
|
would produce |
|
Named parameters
[edit]
If the template __TEMPLATE__
is defined with the code below:
{{#invoke:Enumerate|main|item}}
Then,
{{__TEMPLATE__|item1=A|item2=B|item3=C}}
|
would produce |
|