Module:Wikilisp/doc

This module supports simple but flexible and fairly powerful operations on strings and numbers. It is meant to bring the supported operations within reach of ordinary wiki contributors, by using expressions embedded in wiki markup, and by minimizing the syntactic red tape involved.

Call the module like this:
 * evalx|sequence|...

or
 * #invoke:|rep|sequence|...

where sequence is a series of s-expressions, and there may be additional arguments thereafter (the "|..."). The s-expressions are evaluated, one at a time from left to right, and the result of evaluating the last of them is returned as the expansion of the module-call.

Although this module can be useful for tricky small-scale tasks, it can also do hefty transformations of the entire content of a wiki page, because the entire content of a wiki page is a string.


 * Current version:

S-expressions
The main kinds of values are numbers, strings (that is, unicode text), booleans (true and false), symbols (names for things), and lists.

Numbers, strings, booleans
Numbers and strings are kept separate form each other:  is different from. Evaluating a number or string results in that number or string, unchanged. The result of the module-call, if a simple value (rather than a list, as discussed below), is usually a number or string, unless the module call has an error in it, or is being debugged.

A numeric literal is a series of digits, with an optional decimal point (.), optional sign at the front (+ or -), and optional E notation.

A string literal may be delimited either by double-quotes (") or single-quotes ('), and may contain any characters except the delimiter. If a string needs to involve both single- and double-quotes, the easiest approach is to make the string an additional parameter to the module call; though there is also fully general advanced string syntax.

The boolean values, true and false, usually result from some logical test and are fed as operands into some other operation; so they are usually neither written explicitly into an input expression, nor written as part of an output expression. The boolean values are represented as  and.

Symbols
Any input-text sequence that doesn't represent a string literal or numeric literal, and doesn't contain any whitespace or parentheses or backslash or semicolon, names a symbol. Also, any backslash that isn't inside a string literal names a symbol (the backslash symbol).

A symbol is evaluated by looking it up in the environment. For most (though not all) purposes, there's just one, global environment, defining the standard functions provided for use in expressions. There are advanced situations where you might alter the global environment, or even do some things in a local environment; but this module is really meant to provide powerful, flexible standard functions so you can almost always do the things you want to do without resorting to complicated techniques like that. When you do end up doing such things, it's probably time to think about what even better tools would make them even more rarely needed.

Lists
A list is a sequence of values. It is represented by a set of parentheses, with the values between them, separated by whitespace. A set of parentheses with nothing (but perhaps whitespace) between them represents the empty list.

When evaluating a non-empty list (the empty list evaluates to itself), the first element of the list is the operator and any additional elements are operands. The operator is evaluated first, and what happens thereafter depends on what the operator evaluated to. It must evaluate to a function (if not, that's an error). A few special functions act on their operands directly, without evaluating the operands first; for all other functions, the operands are evaluated, and the results of those evaluations are passed to the function.

Comments
A semicolon in an input expression, not inside a string literal, marks a comment: the interpreter ignores all characters from the semicolon to the end of the line it is on.

Functions
The interpreter is meant to be a simple device for filling in gaps in wiki-markup-based functionality; it is not meant to replace other wiki-markup facilities, and especially not to provide all functionality for template internals. It should not be capable of arbitrary (Turing-powerful) computation. It should provide a small, highly versatile set of functions affording succinct expression of valuable functionality not otherwise well-supported by wiki-markup. These constraints give its choice of supported functions a somewhat different character from those of a general-purpose programming language.

Background stuff
These functions do mundane tasks, filling in the gaps around the powerful tools that do the heavy lifting.


 * Function   returns a list of its operands.  would evaluate to (2 1),  to.


 * The basic arithmetic functions are          . Subtraction and division require at least two operands; the first operand is acted on by all of the others, so would evaluate to 4, and  would evaluate to 2. Exponentiation requires exactly two operands;  would evaluate to 3.


 * Function   also concatenates strings or lists, and combines booleans by logical conjunction. would evaluate to "abcd",  to (1 2 3),  to false.  This only works if the function is given at least one argument, so it knows what type to return; with no arguments, it just assumes it's doing numeric addition:  evaluates to 0.


 * Simple arithmetic functions      each take a single number operand, and return respectively its absolute value, the smallest integer not less than it (its ceiling), and the greatest integer not greater than it (its floor). Thus,  would evaluate to 2.3,  to -2,  to -3; while, , and  would each evaluate to 4.


 * The numeric and string comparison functions are:   (less than),    (greater than),    (less than or equal),    (greater than or equal).  Each function takes zero or more operands, and checks that every pair of consecutive operands have the named relation.  Thus,  would evaluate to true,  would be false because 2 is not greater than 2,  would be false because "def" is not alphabetically before "abc".


 * A general comparison function   determines whether all of its operands are (superficially) the same. Technically, it determines whether all of its operands would appear the same if they were output.  There are some weird situations in which values that aren't really the same might "look" equal, but as long as you stick to numbers, strings, booleans, and lists, such situations won't happen.


 * Each of functions         checks that all of its operands have the named type. So,  would evaluate to true, as would, while  would evaluate to false.  There are a few other types of values, and they have functions to check for them too, but ordinarily you shouldn't need to check for them (they're "advanced" features).


 * Functions   and   take one operand and convert it either way between a number and a string representation of a number. If the operand of   does not represent a number, it returns the empty list.


 * Function   takes two or more operands; first a list, then an integer or integers. With one integer, it returns the nth element of the list.   would evaluate to 7.  With multiple integers n, m, etc., it takes takes the nth element of the list, then expects that to be a list and takes the mth element of that, and so on.


 * Function   takes a single boolean operand, and returns true if the operand is false, false if the operand is true. The corresponding tools   and   are special functions (below).


 * Function   takes a single operand, which can be either a string or a list, and returns its length, as an integer: for a string, this is the number of unicode codepoints, for a list, the number of items on the list.  would evaluate to 0.


 * Functions  ,  ,  ,  ,  ,   each take a single operand, either a string or a list of strings. Given a string,   returns the string with leading and trailing whitespace removed;   with all letters converted to lower-case,   to upper-case;   with the first character converted to lower-case,   to upper case;   converts the first character of the string to a numeric html entity reference, or if the string is empty returns the string.  Given a list of strings, each function applies its operation to each string on the list, and returns a list of the results.   would evaluate to ("ABC" "DEF").   would evaluate to "&amp;#65;" (which would appear as "&#65;");  would evaluate to "".


 * Function   takes a single operand, and produces its output string representation. This is how the operand would appear if it were part of a larger result of computation, such as a list.  If the operand isn't a string, it appears the same way if it is the entire result of computation as if it is embedded in some larger result; however, a string result of computation is output directly, rather than formatted with delimiters.  If a value (barring oddball things like functions and patterns) is meant to be output from one evaluation and input to another, and may be a string,   gives it the proper output format.  For example,  represents a string of length seven with one double-quote character in it, while  would evaluate to a string of length ten with four double-quote characters in it; so  would expand to , while  would expand to.


 * Functions  ,  ,  , and   provide substantially the magic words of the same names, per mw:Help:Magic words. Each takes one or, in some cases, two string operands.  Some examples:  would evaluate to,  to ,  to ;  to ;  to ;  to "h&zwj;".


 * Function   takes a string, taken to be a pattern (in the Scribuntu sense), and returns a pattern object, a separate data type usable in some string-search functions.


 * Function   takes two strings, and splits the first string into a list of its substrings separated by the second string.  would evaluate to ("a" "" "a").  Alternatively, the second string may be a pattern rather than a string;  would evaluate to ("f" "" "b" "r").    also has more general forms described in the next section.


 * Function   takes a list of strings and a string, and concatenates the strings from the list separated by the latter string.  would evaluate to "a,b".    also has more general forms described in the next section.


 * Functions   and   take a string or list, and one or two integers, and return the substring/sublist starting at the element with the first index (counting from 1), and continuing through the element with the second index if any.  would evaluate to "b".   would evaluate to (2 3).    also has more general forms described in the next section.


 * Functions   and   take four operands: a base string/list, two integers describing a segment of the base to be replaced (start/end indices, counting from 1), and a string/list to splice into that segment. A new string/list is returned with the indicated splice.   would evaluate to "fozr".  The second index is included in the segment; to splice between two characters of the base, the second index should be one less than the first:  would evaluate to "a123b".    also has more general forms described in the next section.


 * Function   takes two operands, the first a target string or list in which to search, and returns a list of where matches occur in the target. With a list, the second operand is a function, which is applied to each element of the list and must return a boolean; each matching position is an index into the list (counting from 1).  With a string, the second operand is either a string or pattern, and each matching position is a list of start/end indices (counting from 1).   would evaluate to (1 3).   would evaluate to ((2 2) (3 3)).


 * Function   usually takes two operands, the second of which is a list, and returns true if any member of the list is equal to the first operand (per function, above), otherwise returns false.  If given just one operand,   returns a function that takes a list as operand and returns true or false depending on whether any element of the list is equal to the operand passed to  .   would evaluate to true, as would.


 * Function   takes a function and a list, and calls the function with the operands on the list.  would evaluate to 6.


 * Function   takes a function and one or more additional operands, and returns a function that takes zero or more operands, and calls the earlier operand function with all the operands together, both the earlier ones and the later ones.  would evaluate to 21.   would evaluate to 6.

Special functions, whose operands are not automatically evaluated:


 * Special function   can be used in two different ways. Given operands that evaluate to booleans, it returns true if all the operands evaluate to true, false if one of them evaluates to false; if one of them evaluates to false, it doesn't evaluate later operands.  Given operands that evaluate to functions, it evaluates them all and returns a function that passes all its operands to each of those functions, expecting each of them to return a boolean; again, it returns true if they all return true, or stops and returns false if one of them returns false.   would evaluate to true, because  and  evaluate to true.   would evaluate to false, because  evaluates to false.


 * Special function   is like, with change of form:  if all are false, returns false; if any is true, stops and returns true.   would evaluate to false, because  and  evaluate to false.   would evaluate to true, because  evaluates to true.


 * Special function   takes three operands; as a special function, its operands are not automatically evaluated. It evaluates its first operand, the result of which must be boolean, and then evaluates the second or third operand depending on whether the result from the first was true or false, and returns the result of the latter evaluation.  So  and  would both evaluate to 9.


 * Special function   creates a function. It ordinarily takes two operands; the first is a symbol, which is not evaluated and is the name of the parameter to the new function; the second is the body of the new function. When the function is called, its operand is evaluated, and the parameter is locally bound to the result of this evaluation; then the body of the function is evaluated locally, with the parameter bound to the function argument, and the result of this evaluation of the body is the result of the function call.  For example,  would evaluate to 25.


 * Special function   creates a temporary name for something. It takes at least one (usually two or more) operands; the first operand is a list of a symbol and an expression.  The expression is evaluated, and the result becomes the temporary meaning of the symbol; the remaining operands are evaluated, from left to right, in the local environment so constructed, and the result of the last evaluation is returned (or if there was only the one operand, the empty list is returned).  For example,  would evaluate to 9, while  would evaluate to 6.


 * Special function   modifies the current environment (whereas  creates a new environment for temporary use).  It takes two operands; the first is a symbol.  It evaluates its second operand, and then binds its first operand to the result in the environment.  For example, evaluating   would modify the environment so that   would evaluate to 7; thus,  would expand to 49.


 * Special function   evaluates its operands, in order from left to right, and returns the result of the last evaluation. Given no operands, it returns the empty list.  Handy for conditionally doing a series of things for effect, such as in  which would return true or false and might also change the local values of x and y.  The same thing could be accomplished using functions   and , or just   if you're just going to throw out the result anyway; but besides saving a left of nesting when you do want the result, the name "sequence" makes it clearer what you're doing.

Powerful stuff
These functions do the heavy lifting.


 * Function   retrieves arguments to the module call. It takes one operand, identifying the argument to retrieve; this may be an integer or a string.  Argument 1 is the sequence of s-expressions; thus,  would expand to  "'foobar' (get-arg 1)", while  would expand to "quux".  Function   also retrieves arguments, but instead of returning an argument as a string, it attempts to interpret the argument as an s-expression which it returns unevaluated.  If the argument is not a valid s-expression, the function returns the empty list.  This is handy for doing further computation on a data structure that was output from an earlier call to the interpreter, as perhaps in an earlier step of a dialog.   would expand to  (* 2 3).  Function    retrieves a list of the names of all arguments to the module call.
 * If the module is invoked through alternative Lua function  rather than , wikilisp functions  and  access arguments of the template that invokes the module, instead of arguments of the invocation itself.  Template evalx does this.


 * Function   takes one operand, which must be a text string and is interpreted as raw wiki markup (before template expansion). The function returns a data structure describing the positions, within the text string, of wikilinks, template calls, and template parameters; and, within each such item, the positions of the parts of the item (which are separated from each other by the pipe character, "|").  Other tools can then use this data structure to locate particular kinds of structures within the wiki markup, and transform them in various ways.
 * The data structure is a list of "item" data structures; accessor functions can recover the string form of each item, the number of parts, the string form of each part, and a list of items within each part.
 * Function   takes one operand, an item descriptor as provided by, and returns a list of its parts.  Function   takes one operand, a part descriptor as provided by  , and returns a list of items within it.


 * Function   at its simplest takes two operands: a data structure such as produced by function, and a predicate to be applied to the entries in the structure for links, calls, and parameters.  It returns a pared-down data structure describing only those page elements that match the predicate.  Additional operands are additional predicates that must also be satisfied, as with special function.
 * If the predicate(s) reject an item, but accept some items within one of the rejected item's parts, the accepted items are promoted to the level of the rejected item. For example, suppose a page contains a call to xambox, and within the text message passed to the xambox are some calls to w.  If the page is parsed and filtered for calls to w, the calls within the xambox will end up at the top level of the filtered data structure.
 * Functions     and   are predicates determining whether their operands are item data structures describing, respectively, wikilinks, template calls, and template parameters.
 * Function  isn't designed for selecting some members of an ordinary list, but that can be done by building a new list out of small lists, where each small list either contains a particular element of the original list or is empty.  For example, given a list of numbers , one could select the ones strictly less than 10 with expression .  (Note the trick of  ing   with the empty list before  ing it; otherwise, if   happened to be empty,   would be applied to the empty list, producing a number instead of a list.)


 * Function   can take more general forms of its first operand, and can take either or both of two additional operands, beyond the string and string-or-pattern as in the previous section.
 * There may be a second string-or-pattern operand; instead of listing substrings separated by a single string-or-pattern, the function then lists substrings delimited by the two strings-or-patterns. For example,  would evaluate to ("b" "d").  The delimiters are assumed to be potentially nesting, and at each point in the string the leftmost left-delimiter is chosen that has a matching right-delimiter.  For example,  would evaluate to ("b(c)e" "g(h)i").
 * There may be a final list operand, of 1–3 elements that could be the second-and-later operands to ; if this is present, instead of returning a list of substrings from the aforementioned operation,   recursively splits each of those substrings using this new set of second-and-later operands, and returns a list of the results of these splits.  For example,  would evaluate to ((("b" "c") ("d" "e")) (("g" "h") ("i" "j"))).
 * The first operand, rather than simply a string, can in general be a tree of strings; that is, either a string or a list whose elements are themselves trees of strings. The string operation specified by all the later operands is then applied recursively to each element of the tree.  For example,  would evaluate to (((("b" "c")))(("f" ""))).


 * Function   can take more general forms of its first operand, and can take either or both of two additional operands, beyond the list-of-strings and string as in the previous section.
 * There may be a second string operand; then each of the listed strings is delimited by the two strings. For example,  would evaluate to "{1}{2}".
 * The first operand, rather than simply a list of strings, can in general be a nested list of strings; that is, either a list of strings or a list whose elements are themselves nested lists of strings. The operation specified by the one or two string operands is then applied recursively to each element of the nested list.  For example,  would evaluate to ("a,b" "c,d").
 * There may be a final list operand, of 1–3 elements that could be the second-and-later operands to ; if this is present,   first operates on its first operand using the one or two string operands, then recursively operates on the result using the finally-listed set of operands.  For example,  would evaluate to "{a,b}{c,d}".  Thus   can restore nestings of separators and delimiters removed by  ; for example,  would evaluate to "{b},{e}".


 * Function   can take a descriptor specifying a segment of the string, instead of integer indices as in the previous section. Three kinds of descriptors are accepted:  an item descriptor, which is an element of a list returned by   or  ; a part descriptor, which is an element of a list returned by  ; or a list of two integers, which are the 1-based indices of the starting and ending character of the substring within the string.  The resulting substring is returned.  For example,  would evaluate to "oba".  Alternatively, the second operand can be a list of segment descriptors, and a list of substrings is returned;  would evaluate to ("o" "ba").


 * Function   can take a segment-descriptor (as just described for get-substring) instead of integer indices for where to splice as in the previous section. Alternatively, it can take a list of such segment-descriptors, and a list of strings; the segments must be in order from left to right.   would evaluate to "fo12345r",  to "a123c456d".


 * Function   takes a segment-descriptor (as just described for get-substring) and returns a list of two integers, the 1-based indices fo the starting and ending character of the segment. This is useful for decoding item descriptors and part descriptors so that the coordinates can be manipulated directly for general purposes. For example,  would evaluate to ((3 7) (9 13)).


 * Function   takes a function and one or more lists. It calls the function repeatedly, with one operand from each of the lists, and returns a list of the results.  Usually it is used with just one list; for example,  would evaluate to (1 4 9).  With multiple lists,  would evaluate to (10 21).  If some of the lists are longer than others,   stops when any of the lists runs out; for example,  would evaluate to ((1 3 4)).


 * Function   takes a function and one or more lists. The function should be a binary predicate, for ordering elements of the lists.  Each list is assumed already sorted by the predicate (i.e., the predicate would return true on any two elements of the same list in their order in the list).  The function merges the lists into a single list sorted by the predicate.  If there is only one list, it is simply returned.  For example,  would evaluate to (1 2 3 4 5 6).  This isn't meant to be used with a very large number of lists; it slows down as the square of the number of lists.


 * Function   takes up to four optional operands, and generates a -like function for acting on a tree, that is, a nested list.  The resulting function takes three operands: a function to apply to leaf nodes of the tree, a function to apply to parent nodes of the tree, and a tree.  In the simplest case, with no optional operands, if the tree is not a list then the leaf-function is applied to it and the result returned; while if the tree is a list, each element of the list is recursively transformed and the parent-function is applied to a list of the results.  For example,  would evaluate to (4 (9 16) 25),  to 54.
 * The last optional operand is a positive integer, n. The first n elements of each parent-node list are left alone rather than recursively operated on.  For example,  would evaluate to (2 3 16 25).
 * The first optional operand is a predicate. When the tree is a list, the predicate is applied to it, and if the result is false the tree is treated as a leaf instead of a parent, applying the leaf-function to it instead of recursing and passing a resultant list to the parent-function.  For example,  would evaluate to (("x" "x") "x" ("x" "x")).
 * Between these, the second and third optional operands, which must occur together, are a basis value and a successor function, used to generate an extra, depth operand for the leaf/parent functions: at the top-level node of the tree, this value is the basis, and at each level further down the tree, the value results from applying the successor function to the value used at the level above. The depth operand is passed to the leaf/parent function as its first operand, before the tree-node operand.  For example,  would evaluate to (3 (4 4) 3).  If the predicate operand is also provided, it receives only the tree-node, not the depth.

Advanced stuff
These things may help you better understand the inner workings of the interpreter, and occasionally help you do some unusual things that the more mundane features don't handle cleanly. When you start actively using these exotica to do unusual things, it may be time to look for a way to amplify the ordinary tools so it won't be necessary to resort to these; but that may be a very difficult design problem, and meanwhile these things are available to take up the slack.


 * Special function   can create functions that take different numbers of arguments, and evaluate a sequence of expressions. For different numbers of arguments, instead of a symbol for the first operand, use a list of symbols; the list may be empty, so the function takes no arguments.  To evaluate a sequence of expressions, just specify all of them after the parameter-list.  When the function is called, the number of arguments to the call must be the same as the number of parameters; all the parameters are locally bound to the corresponding arguments, and the second and later operands to   are evaluated in this local environment from left to right.  The result of the last of these evaluations is the result of the function call, or if   was given only one operand, the result of the function call is the empty list.
 * An esoteric point: The local environment, in which the function's sequence of expressions are evaluated, is a child of the environment where   is called (technically, this is called lexical scope).  So when a local environment needs to look up a symbol that isn't locally bound, this occurs where   was called rather than where the created function is called.  For example,  would evaluate to 13.


 * Function   checks whether all the values passed to it are ordinary functions; function   checks whether all the values passed to it are special functions.  would evaluate to false, since   is not an ordinary function.   would evaluate to false since + is not a special function.


 * When an ordinary function is displayed as output, it is shown as name, where name is the name of the function. For example,  would expand to .  The angle-brackets mean that the operands to the function call are automatically evaluated; underneath is a special function whose operands are the results of evaluating the operands to the ordinary function call.  Evaluating  would not produce an error until after the operand has been evaluated to 3, at which point the special function underlying   would discover it doesn't know what to do with an integer operand, producing error message.


 * When special function  creates a function, it doesn't give it a name.   would expand to  .  However, the first time an anonymous function is given a name in an environment, that name is attached to the function, and the function is known by that name thereafter.  So,  would expand to.


 * There is a built-in limit on how deeply calls to -defined functions can be nested.  At the current writing, the limit is 4.  That is,   would evaluate to 2,   to 4, and   to 8, but   would produce.


 * If you really need to embed a double-quote in a string literal delimited by double-quotes, use two double-quotes inside the literal.   is the empty string;   is a string of length one, containing a single double-quote.  There is no analogous way to embed a single-quote in a string literal delimited by single-quotes.


 * Function   provides a string describing the current version of the module.   currently evaluates to.

Module tests
These aren't exhaustive. They aspire to exercise all of the code in the module at least once (both branches of an if, etc.), though there would be merit to deskchecking all the code to determine what parts of it have been overlooked. {{hidden|Module tests| {{module test case|top=1}} {{module test case|rep|expected=|description=No tokens}} {{module test case|rep|-10|expected=-10|description=No whitespace}} {{module test case|rep| (list 8 false true length) |expected=( 8 false true &lt;[op: length]&gt; )|description=Token classes (tok3)}} {{module test case|rep| (list 2 ( 4 5) |expected=&lt;error: unmatched left-paren&gt;|description=Unbalenced left paren}} {{module test case|rep| (list 2 ) 4 5) |expected=&lt;error: unmatched right-paren&gt;|description=Unbalenced right paren}} {{module test case|rep| (list (+ 1; ;2  3) (+ "a" ; "b   'c' ; 'd   ); foo (+ "a;b" 'c;d') ) |expected=( 4 "ac" "a;bc;d" )|description=comments}} {{module test case|rep| (list 1 2 3 (list 4 5 6 (list))) |expected=( 1 2 3 ( 4 5 6  ) )|description=Nested lists}} {{module test case|rep| (list " ' ') |expected=&lt;error: mismatched string-literal delimiter (")&gt;|description=Unbalenced double-quote}} {{module test case|rep| (list  ' " \" ") |expected=&lt;error: mismatched string-literal delimiter (')&gt;|description=Unbalenced single-quote}} {{module test case|rep| (list " ' " 2 '"\"\') |expected=( " ' " 2 """\""\" )|description=String literals}} {{module test case|rep| (list + if (\ )) |expected=( &lt;[op: add]&gt; [op: if] &lt;[op]&gt; )|description=Write combiners}} {{module test case|rep| 'foo bar " quux' |expected=foo bar " quux|description=Display string}} {{module test case|rep| (list foo) | expected=&lt;error: undefined symbol: foo&gt;|description=Undefined symbol}} {{module test case|rep| () | expected=&lt;error: called object is not a combiner: &gt;|description=Eval nil; call non-combiner}} {{module test case|rep| (let (g (\f (\x (f (f x))))) ((g (g (g (g (\x (+ 1 x)))))) 0)) |expected=&lt;error: exceeded maximum call-nesting depth (4)&gt;|description=Call-nesting beyond depth limit of 4}} {{module test case|rep| (+ +) |expected=&lt;error: bad operand to [op: add]: expected number, string, boolean, or list, got &lt;[op: add]&gt;&gt;|description=Ordinary operand type error}} {{module test case|rep| (split "foo" 3) |expected=&lt;error: bad operand to [op: split]: expected string or pattern, got 3&gt;|description=Operand type error, multiple types for non-initial operand}} {{module test case|rep| (set-substring ) |expected=&lt;error: bad operand to [op: set-substring]: expected string, got &gt;|description=Operand type error, redundantly listed type}} {{module test case|rep| (/ 3 "3456789a123456789b123456789c123456789d123456789e123456789f12345") |expected=&lt;error: bad operand to [op: divide]: expected number, got string&gt;|description=Operand type error, verbose operand}} {{module test case|rep| (- ) |expected=&lt;error: too few operands to [op: subtract]: expected at least 2, got 1&gt;|description=Too few operands, open arity}} {{module test case|rep| (if) |expected=&lt;error: wrong number of operands to [op: if]: expected 3, got 0&gt;|description=Too few operands, fixed arity}} {{module test case|rep| (get-sublist ) | expected=&lt;error: too few operands to [op: get-sublist]: expected at least 2, got 1&gt;|description=Too few operands, range arity}} {{module test case|rep| (if 1 2 3 4) |expected=&lt;error: wrong number of operands to [op: if]: expected 3, got 4&gt;|description=Too many operands, fixed arity}} {{module test case|rep| (get-substring "" 1 2 3) |expected=&lt;error: too many operands to [op: get-substring]: expected at most 3, got 4&gt;|description=Too many operands, range arity}} {{module test case|rep| (list (le?) (le? 2) (le? 2 3) (le? 2 1) (le? 1 2 3) (le? 2 1 3) (le? 1 3 2)) |expected=( true true true false true false false )|description=Binary predicate}} {{module test case|rep| (list (boolean?) (boolean? true) (boolean? false false) (boolean? true 7) (boolean? 3 false)) |expected=( true true true false false )|description=Unary predicate}} {{module test case|rep| (\ 4) |expected=&lt;error: bad parameter-list operand to [op: \]: 4&gt;|description=Parameter list not a list}} {{module test case|rep| (\ ( x y)) |expected=&lt;error: bad parameter-list operand to [op: \]: ( x y )&gt;|description=First parameter not a symbol}} {{module test case|rep| (\ (x y )) |expected=&lt;error: bad parameter-list operand to [op: \]: ( x y )&gt;|description=Last parameter not a symbol}} {{module test case|rep| (list (\ ) (\ x) (\ (x y))) |expected=( &lt;[op]&gt; &lt;[op]&gt; &lt;[op]&gt; )|description=Parameter lists}} {{module test case|rep| (list ((\ )) ((\x (* x x)) 2) ((\ (a b c) (list c a b)) 3 4 5) ) |expected=( 4 ( 5 3 4 ) )|description=Match parameters}} {{module test case|rep| (list (list) (list (+) (+ 8) (+ 1 2) (+ "a" "b" "c") (+ (list 1) (list 2 3))) (- 1 2) (*) (* 8) (* 2 3) (/ 6 3) (list (lt? 1 2) (lt? 2 2) (lt? 2 1) (lt? "a" "b") (lt? "b" "b") (lt? "b" "a")) (list (le? 1 2) (le? 2 2) (le? 2 1) (le? "a" "b") (le? "b" "b") (le? "b" "a")) (list (gt? 1 2) (gt? 2 2) (gt? 2 1) (gt? "a" "b") (gt? "b" "b") (gt? "b" "a")) (list (ge? 1 2) (ge? 2 2) (ge? 2 1) (ge? "a" "b") (ge? "b" "b") (ge? "b" "a")) (not? false)) |expected=( ( 0 8 3 "abc" ( 1 2 3 ) ) -1 1 8 6 2 ( true false false true false false ) ( true true false true true false ) ( false false true false false true ) ( false true true false true true ) true )|description=list + - * / lt? le? gt? ge? not?}} {{module test case|rep| (list (^ 3 2) (^ 4 0.5) (map abs (list 2 0 -1)) (map ceil (list 3 1.3 -1.3)) (map floor (list 3 1.3 -1.3))) |expected=( 9 2 ( 2 0 1 ) ( 3 2 -1 ) ( 3 1 -2 ) )|description=^ abs ceil floor}} {{module test case|rep| (list (list? ) (list? 3) (string? "") (string? 3) (number? 3) (number? list) (symbol? ) (boolean? true) (boolean? 3) (fn? list) (fn? 2) (op? if) (op? +)) |expected=( true false true false true false false true false true false true false )|description=list? string? number? symbol? boolean? fn? op?}} {{module test case|rep| (if 1 2 3) |expected=&lt;error: bad test-result in [op: if]: 1&gt;|description=if non-boolean test result}} {{module test case|rep| (list (length "foo") (length (list 3 3)) (if (lt? 1 2) (- 3 2) x) (if false x (+ 4 5)) ) |expected=( 3 2 1 9 )|description=length if}} {{module test case|rep| (define (foo) 2) |expected=&lt;error: bad definiend to [op: define]: expected symbol, got ( foo )&gt;|description=define non-symbol definiend}} {{module test case|rep| (define x 3) (define f (\ )) (list x f (f))|expected=( 3 &lt;[op: f]&gt; )|description=define}} {{module test case|rep| (define f (\ (+ -) (* 3 4) (list - +))) (list f (f 7 8)) |expected=( &lt;[op: f]&gt; ( 8 7 ) )|description=\ (realistically, most aspects of \ are exercised by earlier tests))}} {{module test case|rep| (list (get-arg 1) (get-arg "2") (get-arg 3) (get-arg 4) (get-arg 5)) | second || fourth |expected=( " (list (get-arg 1) (get-arg ""2"") (get-arg 3) (get-arg 4) (get-arg 5)) " " second " "" " fourth " )|description=get-arg}} {{module test case|rep| (list (parse (get-arg 2)) (parse (get-arg 3)) (parse "foo")) | {{!}} {{(*}}{{(*}}{{(*}}{{(*}}foo{{!}}{{!}}bar{{*)}}{{*)}} {{*)}}{{*)}} | {{(*}}{{(*}}{{(*}}{{(*}}  {{*)}}{{*)}}{{*)}} |expected=( ( ( "call" ( 4 20 ) ( "part" ( 6 18 ) ( "call" ( 6 17 ) ( "part" ( 8 10 ) ) ( "part" ( 12 11 ) ) ( "part" ( 13 15 ) ) ) ) ) ) ( ( "param" ( 3 14 ) ( "part" ( 6 11 ) ( "link" ( 7 10 ) ( "part" ( 9 8 ) ) ) ) ) )  )|description=parse: leading non-left, non-final call, final call, multiple parts, consecutive pipes, new left-index; unused top-level entry, wikilink, parameter, featureless input}} {{module test case|rep| (nth (list 3 5 7) 0) |expected=&lt;error: bad operand to [op: nth]: expected positive integer, got 0&gt;|description=nth index too low}} {{module test case|rep| (nth (list 3 5 7) "foo") |expected=&lt;error: bad operand to [op: nth]: expected positive integer, got "foo"&gt;|description=nth index non-numeric}} {{module test case|rep| (nth (list 1 (list 3 5 7)) 2 4) |expected=&lt;error: bad index to [op: nth]: asked for 4, list length is 3&gt;|description=nth index too high}} {{module test case|rep| (nth (list 3 5 7) 1.1) |expected=&lt;error: bad operand to [op: nth]: expected positive integer, got 1.1&gt;|description=nth index fractional}} {{module test case|rep| (nth (list "") 1 1) |expected=&lt;error: bad multi-index to [op: nth]: tree too shallow&gt;|description=nth tree too shallow}} {{module test case|rep| (list (nth (list 3 5 7) 2) (nth (list (list 1 2 3) (list 4 5 6) (list 7 8 9)) 3 1)) |expected=( 5 7 )|description=nth}} {{module test case|rep| (list (and?) (and? true false "foo") ((and? boolean? if) false false true) ((and? number? gt?) "foo")) |expected=( true false true false )|description=and?, non-error}} {{module test case|rep| (and? "foo") |expected=&lt;error: bad operand to [op: and?]: expected boolean or combiner, got "foo"&gt;|description=and? first-order operand type error, leftmost}} {{module test case|rep| (and? true number?) |expected=&lt;error: bad operand to [op: and?]: expected boolean, got &lt;[op: number?]&gt;&gt;|description=and? first-order operand type error, after boolean}} {{module test case|rep| (and? number? true) |expected=&lt;error: bad operand to [op: and?]: expected combiner, got true&gt;|description=and? first-order operand type error, after combiner}} {{module test case|rep| ((and? gt?) true) |expected=&lt;error: bad operand to [op: gt?]: expected number or string, got true&gt;|description=and? second-order operand type error}} {{module test case|rep| (list (or?) (or? false true "foo") ((or? string? if) false "foo" true) ((or? string? gt?) "foo")) |expected=( false true true true )|description=or?, non-error}} {{module test case|rep| (or? "foo") |expected=&lt;error: bad operand to [op: or?]: expected boolean or combiner, got "foo"&gt;|description=or? first-order operand type error, leftmost}} {{module test case|rep| (or? false number?) |expected=&lt;error: bad operand to [op: or?]: expected boolean, got &lt;[op: number?]&gt;&gt;|description=or? first-order operand type error, after boolean}} {{module test case|rep| (or? number? true) |expected=&lt;error: bad operand to [op: or?]: expected combiner, got true&gt;|description=or? first-order operand type error, after combiner}} {{module test case|rep| ((or? gt?) false) |expected=&lt;error: bad operand to [op: gt?]: expected number or string, got false&gt;|description=or? second-order operand type error}} {{module test case|rep| (filter (parse (get-arg 2)) nth) | foo |expected=&lt;error: too few operands to [op: nth]: expected at least 2, got 1&gt;|description=filter predicate reports error}} {{module test case|rep| (filter (parse (get-arg 2)) length nth) | foo |expected=&lt;error: bad operand to [op: and?]: expected boolean, got 3&gt;|description=filter predicate returns non-boolean, later predicate would have reported error}} {{module test case|rep| (define t (parse (get-arg 2))) (list (filter t (\x false) nth) (filter t (\x (equal? (nth x 1) "link")))) | foo {{(*}}{{(*}}foo{{*)}}{{*)}} foo{{!}} [[bar {{(*}}{{(*}}bar{{*)}}{{*)}} ]] {{(*}}{{(*}}foo{{!}} bar {{(*}}{{(*}}bar{{*)}}{{*)}} {{*)}}{{*)}} |expected=( ( ( "link" ( 2 8 ) ( "part" ( 4 6 ) ) ) ( "link" ( 18 42 ) ( "part" ( 20 22 ) ) ( "part" ( 24 40 ) ( "link" ( 25 31 ) ( "part" ( 27 29 ) ) ) ) ) ( "link" ( 51 57 ) ( "part" ( 53 55 ) ) ) ) )|description=filter: false predicate cutting off later error, items included or omitted with or without sub-items}} {{module test case|rep| (filter (list 3 "foo" 4 "bar") string?) |expected=( "foo" "bar" )|description=filter: non-list items}} {{module test case|rep| (list (link? 3) (call? 3) (param? 3) (link? ) (call? ) (param? ) (link? (list 3)) (call? (list 3)) (param? (list 3)) (link? (list "param")) (call? (list "link")) (param? (list "call")) (link? (list "link")) (call? (list "call")) (param? (list "param"))) |expected=( false false false false false false false false false false false false true true true )|description=link? call? param?}} {{module test case|rep| (get-parts (list "foo")) |expected=&lt;error: bad operand to [op: get-parts]: expected item, got ( "foo" )&gt;|description=get-parts list too short}} {{module test case|rep| (get-items ) |expected=&lt;error: bad operand to [op: get-items]: expected part, got &gt;|description=get-items list too short}} {{module test case|rep| (get-items (nth (get-parts (nth (parse (get-arg 2)) 1)) 2)) | {{{(*}}{{(*}}{foo {{!}}  bar}{{*)}}{{*)}} |expected=( ( "link" ( 17 20 ) ( "part" ( 19 18 ) ) ) )|description=get-parts, get-items}} {{module test case|rep| (define p (parse (get-arg 2))) (list (get-coords (nth p 1)) (get-coords (nth (get-parts (nth p 1)) 2))) | {{{(*}}{{(*}}{foo {{!}}  bar}{{*)}}{{*)}} |expected=( ( 3 27 ) ( 16 24 ) )|description=get-coords}} {{module test case|rep| (define s (get-arg 2)) (define t (parse s)) (list (get-substring s (nth t 1)) (get-substring s (nth (get-parts (nth t 1)) 2))) | {{{(*}}{{(*}}{foo {{!}}  bar}{{*)}}{{*)}} |expected=( "{{(*}}{{(*}}{{(*}}foo  {{!}}  bar{{*)}}{{*)}}{{*)}}" "  bar" )|description=get-substring items, parts}} {{module test case|rep| (define s "foobar") (define s2 (get-substring s 2 5)) (list (get-substring s -2 1) (get-substring s (list 2 5)) (get-substring s (list (list -1 8))) (get-substring s2 (list (list 2 3) (list 1 8)))) |expected=( "f" "ooba" ( "foobar" ) ( "ob" "ooba" ) )|description=get-substring integers; coordinate-lists; lists of coordinate-lists}} {{module test case|rep| (get-substring "foo" (list 2 2 2)) |expected=&lt;error: bad operand to [op: get-substring]: expected integer, coordinates descriptor, or list of coordinates descriptors, got ( 2 2 2 )&gt;|description=ipcs_tc coords list too long}} {{module test case|rep| (get-substring "foo" (list 2 "x")) |expected=&lt;error: bad operand to [op: get-substring]: expected integer, coordinates descriptor, or list of coordinates descriptors, got ( 2 "x" )&gt;|description=ipcs_tc coords truncated item}}

{{module test case|rep| (set-substring "abc" 0 1 "123") |expected=&lt;error: bounds violation in [op: set-substring]: segment starts left of string start (0)&gt;|description=set-substring, segment starts before string}} {{module test case|rep| (set-substring "abc" 3 4 "123") |expected=&lt;error: bounds violation in [op: set-substring]: segment ends right of string end (4, 3)&gt;|description=set-substring, segment ends after string}} {{module test case|rep| (set-substring "abc" 3 1 "123") |expected=&lt;error: bounds violation in [op: set-substring]: segment starts right of its own end (3, 1)&gt;|description=set-substring, segments ends before starts}} {{module test case|rep| (set-substring "abcdef" (list (list 2 4) (list 3 5)) (list "1" "2")) |expected=&lt;error: bounds violation in [op: set-substring]: segment ends right of next segment start (4, 3)&gt;|description=set-substring, segment ends after next begins}} {{module test case|rep| (list (set-substring "123" 1 0 "a") (set-substring "12345" (list 2 2) "abc") (set-substring "abc" (list (list 2 2)) (list "1" "2")) (set-substring "abc" (list (list 2 2)) ) (set-substring "ab" (list (list 2 1) (list 2 1)) (list "1" "2"))) |expected=( "a123" "1abc345" "a1c" "abc" "a12b" )|description=set-substring}}

{{module test case|rep| (list (split "1,2,3" ",") (split "foobar" "z") (split "abcdbc" "bc") (split "ab" "a") (split "foobar" (pattern "[oa]")) (split "foo)bar" "(" ")") (split "foo(b)a(r" "(" ")") (split "a(b(c(d)e)f)g(h(ij" (pattern "%(") (pattern "%)")) (split "a(b(c)d(e)f)g(h)i" "(" ")" (list "(" ")")) (split (list (list) (list "c,d") "a,b") ",")) |expected=( ( "1" "2" "3" ) ( "foobar" ) ( "a" "d" "" ) ( "" "b" ) ( "f" "" "b" "r" ) ( "b" ) ( "b(c(d)e)f" "" ) ( ( "c" "e" )  ) (  ( ( "c" "d" ) ) ( "a" "b" ) ) )|description=split}} {{module test case|rep| (list (get-sublist (list 1 2 3) 2) (get-sublist (list 1 2 3) 2 4)) |expected=( ( 2 3 ) ( 2 3 ) )|description=get-sublist}} {{module test case|rep| (find (list 1 2 3) (\x )) |expected=&lt;error: bad predicate result type to [op: find]: got list&gt;|description=find, predicate returns non-boolean}} {{module test case|rep| (find (list true) lt?) |expected=&lt;error: bad operand to [op: lt?]: expected number or string, got true&gt;|description=find, predicate throws error}} {{module test case|rep| (find ":" "") |expected=|description=find, empty string in nonempty string}} {{module test case|rep| (find ":" (pattern "")) |expected=|description=find, empty pattern in nonempty string}} {{module test case|rep| (list (find (list (list 1) 2 3 "d") number?) (find (list 1 2 3) string?) (find "foobar" "o") (find "foobar" (pattern "[ao]")) (find "quux" (pattern "[ao]"))) |expected=( ( 2 3 ) ( ( 2 2 ) ( 3 3 ) ) ( ( 2 2 ) ( 3 3 ) ( 5 5 ) )  )|description=find}} {{module test case|rep| (list (set-sublist (list 1 2 3) -2 1 (list "a" "b")) (set-sublist (list 1 2 3) 2 0 (list "a")) (set-sublist (list 1 2 3 4) 2 3 )) |expected=( ( "a" "b" 2 3 ) ( 1 "a" 2 3 ) ( 1 4 ) )|description=set-sublist}} {{module test case|rep| (map + (list 1) (list "a")) |expected=&lt;error: bad operand to [op: add]: expected number, got "a"&gt;|description=map, error from mapped function}} {{module test case|rep| (list (apply + (list 1 2)) (map (\x (* x x)) (list 2 3)) (map + (list 1 "a" (list 2)) (list 3 "b")) ((curry * 2 3) 4 5)) |expected=( 3 ( 4 9 ) ( 4 "ab" ) 120 )|description=apply, map, curry}} {{module test case|rep| (list (member? 2 ) ((member? 2) ) (member? 1 (list 2 3)) ((member? 1) (list 2 3)) (member? 1 (list 2 1)) ((member? 1) (list 2 1))) |expected=( false false false false true true )|description=member?}} {{module test case|rep| (list (trim " a b c ") (trim (list " 1 ")) (lc "abc") (lc "ABC") (lc (list "abc" "ABC")) (lcfirst "abc") (lcfirst "ABC") (lcfirst (list "abc" "ABC")) (uc "abc") (uc "ABC") (uc (list "abc" "ABC")) (ucfirst "abc") (ucfirst "ABC") (ucfirst (list "abc" "ABC"))) |expected=( "a b c" ( "1" ) "abc" "abc" ( "abc" "abc" ) "abc" "aBC" ( "abc" "aBC" ) "ABC" "ABC" ( "ABC" "ABC" ) "Abc" "ABC" ( "Abc" "ABC" ) )|description=trim, lc, lcfirst, uc, ucfirst}} {{module test case|rep| (define ls (list "ABC" "DEF" "" "GHI")) (equal? (list "&#65;" "&#68;" "" "&#71;") (to-entity ls) (map to-entity ls)) |expected=true|description=to-entity}} {{module test case|rep| (let (x 3) (+ x (let (x 4) x))) |expected=7|description=let}} {{module test case|rep| (list (to-number "314.159265e-2") (to-number "foo") (to-number (get-substring "4567" 2 3)) (to-string 314.159265e-2)) |expected=( 3.14159265 56 "3.14159265" )|description=to-number, to-string}} {{module test case|rep| (define x 3) (sequence (define x 2)) (let (y 1) (define x 0)) (list x (sequence) (sequence 1) (sequence 1 2)) |expected=( 2 1 2 )|description=sequence}} {{module test case|rep| (define t (list 2 3 (list 4 5) 6 (list 7 8))) (list ((transformer) (\x (* x x)) (\x x) t)       ((transformer 1) (\x (* x x)) (\x x) t)        ((transformer (\x (and? (ge? (length x) 1) (le? (nth x 1) 4)))) (\x "x") (\x x) t)       ((transformer (\x (and? (ge? (length x) 1) (le? (nth x 1) 4))) 1) (\x "x") (\x x) t)       ((transformer 2 (\x (+ x 1))) (\(n x) n) (\(n x) x) t)        ((transformer (\x (and? (ge? (length x) 1) (le? (nth x 1) 4))) 2 (\x (+ x 1))) (\(n x) n) (\(n x) x) t)       ((transformer -3 (\x (+ x 1)) 1) (\(n x) n) (\(n x) x) t)        ((transformer (\x (and? (ge? (length x) 1) (le? (nth x 1) 4))) -3 (\x (+ x 1)) 1) (\(n x) n) (\(n x) x) t) ) |expected=( ( 4 9 ( 16 25 ) 36 ( 49 64 ) ) ( 2 9 ( 4 25 ) 36 ( 7 64 ) ) ( "x" "x" ( "x" "x" ) "x" "x" ) ( 2 "x" ( 4 "x" ) "x" "x" ) ( 3 3 ( 4 4 ) 3 ( 4 4 ) ) ( 3 3 ( 4 4 ) 3 3 ) ( 2 -2 ( 4 -1 ) -2 ( 7 -1 ) ) ( 2 -2 ( 4 -1 ) -2 -2 ) )|description=transformer, non-error}} {{module test case|rep| (transformer true 3) |expected=&lt;error: bad operand to [op: transformer]: expected fn, got 3&gt;|description=transformer, boolean parameter}} {{module test case|rep| (transformer list? true) |expected=&lt;error: too few operands to [op: transformer]: expected at least 3, got 2&gt;|description=transformer, fn-boolean parameters}} {{module test case|rep| ((transformer (\x (* x x))) list? list? ) |expected=&lt;error: bad operand to [op: multiply]: expected number, got &gt;|description=transformer, predicate error}} {{module test case|rep| ((transformer (\x "")) list? list? ) |expected=&lt;error: bad predicate result type to [op transform]: string&gt;|description=transformer, non-boolean predicate result}} {{module test case|rep| ((transformer) list? (\x (- x x)) ) |expected=&lt;error: bad operand to [op: subtract]: expected number, got &gt;|description=transformer, error from recursive call}} {{module test case|rep| (list (get-arg-expr 2) (get-arg-expr 3)) | (* 2 3) | ( |expected=( ( * 2 3 ) )|description=get-arg-expr, non-error}} {{module test case|rep| (list (write "foo""bar") (urlencode "fo'o bar") (urlencode "fo'o bar" "path") (urlencode "fo'o bar" "wiki") (anchorencode "fo'o bar") (fullurl "fo'o bar" "qu'ux baz") (canonicalurl "fo'o bar")) |expected=( """foo""""bar""" "fo%27o+bar" "fo%27o%20bar" "fo%27o_bar" "fo&#039;o_bar" "//en.{{lc:{{SITENAME}}}}.org/w/index.php?title=Fo%27o_bar&qu%27ux+baz" "https://en.{{lc:{{SITENAME}}}}.org/wiki/Fo%27o_bar" )|description=write, urlencode, anchorencode, fullurl, canonicalurl}} {{module test case|rep| (list (join  ",") (join  "(" ")") (join (list "a") ",") (join (list "a") "(" ")") (join (list (list "a" "b")) ",") (join (list (list "a" "b")) "(" ")") (join (list (list (list "a" "b") (list "c" "d")) (list (list "e" "f") (list "g" "h"))) "," (list "(" ")" (list ";")))) |expected=( "" "" "a" "(a)" ( "a,b" ) ( "(a)(b)" ) "(a,b)(c,d);(e,f)(g,h)" )|description=join, non-error}} {{module test case|rep| (join (list "a" "b") "," (list "(" ")")) |expected=&lt;error: bad target for [op: join]: tree not deep enough&gt;|description=join, not-deep-enough error}} {{module test case|rep| (join (list (list "a" )) "," (list "(" ")")) |expected=&lt;error: bad target for [op: join]: uneven tree depth&gt;|description=join, uneven-depth error: sep, string first; nested}} {{module test case|rep| (join (list (list "a")) ",") |expected=&lt;error: bad target for [op: join]: uneven tree depth&gt;|description=join, uneven-depth error: sep, list first}} {{module test case|rep| (join (list (list "a" )) "(" ")") |expected=&lt;error: bad target for [op: join]: uneven tree depth&gt;|description=join, uneven-depth error: delim, string first}} {{module test case|rep| (join (list (list "a")) "(" ")") |expected=&lt;error: bad target for [op: join]: uneven tree depth&gt;|description=join, uneven-depth error: delim, string first}} {{module test case|rep| (list (merge le? (list)) (merge le? (list 1 3 2)) (merge le? (list 2 4 6) (list 1 5 3)) (merge le? (list 1 5 7 12 14 18) (list 2 4 9 10 15 17) (list 3 6 8 11 13 16)) (merge le? (list 1 7 8) (list 6 9) (list 2 5 10) (list 4) (list 3 11))) |expected=( ( 1 3 2 ) ( 1 2 4 5 3 6 ) ( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ) ( 1 2 3 4 5 6 7 8 9 10 11 ) )|description=merge}} {{module test case|trep| (list (get-arg "description") (get-arg 1) (get-arg-expr 2) (get-arg-expr 3)) | (+ 1 2 3) |expected=( "trep" "trep" ( list ( get-arg "description" ) ( get-arg 1 ) ( get-arg-expr 2 ) ( get-arg-expr 3 ) ) ( + 1 2 3 ) )|description=trep}} {{module test case|rep| (map (\x (list x (get-arg x))) (get-args)) |foobar|expected=( ( 1 " (map (\x (list x (get-arg x))) (get-args)) " ) ( 2 "foobar" ) ( 3 "" ) ( 4 "" ) )|description=get-args (rep)}} {{module test case|trep| (get-args) |foobar|expected=( 1 2 3 "description" "expected" )|description=get-args (trep)}} {{module test case|bottom=1}} }}