Variadic function
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Create a function which takes in a variable number of arguments and prints each one on its own line. Also show, if possible in your language, how to call the function on a list of arguments constructed at runtime.
Functions of this type are also known as Variadic Functions.
ActionScript
<actionscript> public function printArgs(... args):void {
for (var i:int = 0; i < args.length; i++) trace(args[i]);
} </actionscript>
ALGOL 68
Variable arguments of arbitrarily typed values are not permitted in ALGOL 68. However a flexible array of tagged types (union) is permitted. This effectively allows the passing of strongly typed variable arguments to procedures.
MODE STRINT = UNION(STRING, INT, PROC(REF FILE)VOID, VOID); PROC print strint = (FLEX[]STRINT argv)VOID: ( FOR i TO UPB argv DO CASE argv[i] IN (INT i):printf(($d$,i)), (STRING s):print(s), (PROC(REF FILE)VOID f):f(stand out), (VOID):print(error char) # print a "*" # ESAC; IF i NE UPB argv THEN print((space)) FI OD ); print strint((new page, "Mary", "had", 1, "little", EMPTY, "...", new line))
Output:
<newpage> Mary had 1 little * ...
Also note that EMPTY (of type VOID) can be used to indicate missing or optional arguments.
ALGOL 68 does not have anything similar the keyword argument found in python.
BASIC
Using variable arguments has not been standardised in BASIC. Therefore there are several different implementations, and many BASIC versions do not have this feature at all.
Variadic functions on FreeBASIC are somewhat similar to those in C. The parameter list does not pass information about parameter type. If necessary, the type information has to be passed for example in the first parameter. C calling convention has to be used (with keyword cdecl). <freebasic> SUB printAll cdecl (count As Integer, ... )
DIM arg AS Any Ptr DIM i AS Integer
arg = va_first() FOR i = 1 To count PRINT va_arg(arg, Double) arg = va_next(arg, Double) NEXT i
END SUB
printAll 3, 3.1415, 1.4142, 2.71828 </freebasic> For some reason, I was not able to get a Strings version of the above to work.
Beta BASIC uses keyword DATA to specify variable parameter list. The parameters are read with READ command just like when reading conventional DATA statements. The existence of more parameters as well as the type of each parameter can be checked with function ITEM().
100 DEF PROC printAll DATA 110 DO UNTIL ITEM()=0 120 IF ITEM()=1 THEN READ a$ PRINT a$ 130 ELSE READ num PRINT num 140 LOOP 150 END PROC 200 printAll 3.1415, 1.4142, 2.71828 210 printAll "Mary", "had", "a", "little", "lamb"
The code above is for Beta BASIC. There is a small difference between Beta BASIC and SAM BASIC. On Beta BASIC, the function ITEM has empty parenthesis, on SAM BASIC the parenthesis are not used.
See also: RapidQ
C
The ANSI C standard header stdarg.h defines macros for low-level access to the parameter stack. It does not know the number or types of these parameters; this is specified by the required initial parameter(s). For example, it could be a simple count or a more complicated parameter specification, like a printf() format string. <c>#include <stdio.h>
- include <stdarg.h>
void varstrings(int count, ...) /* the ellipsis indicates variable arguments */ {
va_list args; va_start(args, count); while (count--) puts(va_arg(args, char *)); va_end(args);
}
varstrings(5, "Mary", "had", "a", "little", "lamb");</c>
Common Lisp
The &rest
lambda list keyword causes all remaining arguments to be bound to the following variable.
(defun example (&rest args) (dolist (arg args) (print arg)))
(example "Mary" "had" "a" "little" "lamb") (let ((args '("Mary" "had" "a" "little" "lamb"))) (apply #'example args))
E
Varargs is mildly unidiomatic in E, as the argument count is dispatched on, and often considered part of the method name.
However, accepting any number of arguments can easily be done, as it is just a particular case of the basic mechanism for dynamic message handling:
def example { match [`run`, args] { for x in args { println(x) } } }
example("Mary", "had", "a", "little", "lamb") E.call(example, "run", ["Mary", "had", "a", "little", "lamb"])
For comparison, a plain method doing the same thing for exactly two arguments would be like this:
def non_example { to run(x, y) { println(x) println(y) } }
or, written using the function syntax,
def non_example(x, y) { println(x) println(y) }
Forth
Words taking variable numbers of arguments may be written by specifying the number of parameters to operate upon as the top parameter. There are two standard words which operate this way: PICK and ROLL.
: sum ( x_1 ... x_n n -- sum ) 1 ?do + loop ; 4 3 2 1 4 sum . \ 10
Alternatively, you can operate upon the entire parameter stack for debugging by using the word DEPTH, which returns the number of items currently on the stack.
: .stack ( -- ) depth 0 ?do i pick . loop ;
Haskell
You can use some fancy recursive type-class instancing to make a function that takes an unlimited number of arguments. This is how, for example, printf works in Haskell.
class PrintAllType t where process :: [String] -> t instance PrintAllType (IO a) where process args = do mapM_ putStrLn args return undefined instance (Show a, PrintAllType r) => PrintAllType (a -> r) where process args = \a -> process (args ++ [show a]) printAll :: (PrintAllType t) => t printAll = process [] main :: IO () main = do printAll 5 "Mary" "had" "a" "little" "lamb" printAll 4 3 5 printAll "Rosetta" "Code" "Is" "Awseome!"
So here we created a type class specially for the use of this variable-argument function. The type class specifies a function, which takes as an argument some kind of accumulated state of the arguments so far, and returns the type of the type class. Here I chose to accumulate a list of the string representations of each of the arguments; this is not the only way to do it; for example, you could choose to print them directly and just accumulate the IO monad.
We need two kinds of instances of this type class. There is the "base case" instance, which has the type that can be thought of as the "return type" of the vararg function. It describes what to do when we are "done" with our arguments. Here we just take the accumulated list of strings and print them, one per line. (We actually wanted to use "IO ()" instead of "IO a"; but since you can't instance just a specialization like "IO ()", we used "IO a" but return "undefined" to make sure nobody uses it.) You can have multiple base case instances; for example, you might want an instances that returns the result as a string instead of printing it. This is how "printf" in Haskell can either print to stdout or print to string (like sprintf in other languages), depending on the type of its context.
The other kind of instance is the "recursive case". It describes what happens when you come across an argument. Here we simply append its string representation to the end of our previous "accumulated state", and then pass that state onto the next iteration. Make sure to specify the requirements of the types of the arguments; here I just required that each argument be an instance of Show (so you can use "show" to get the string representation), but it might be different for you.
Icon
varargs.icn
procedure main () varargs("some", "extra", "args") end procedure varargs(args[]) every write( args[1 to *args]) end
Using it
|icon varargs.icn some extra args
Io
printAll := method(call message arguments foreach(println))
Java
Using ... after the type of argument will take in any number of arguments and put them all in one array of the given type with the given name. <java>public static void printAll(Object... things){
for(Object i:things){ System.out.println(i); }
}</java> This function can be called with any number of arguments: <java>printAll(4, 3, 5, 6, 4, 3); printAll(4, 3, 5); printAll("Rosetta", "Code", "Is", "Awseome!");</java>
Or with an array directly: <java>Object[] args = {"Rosetta", "Code", "Is", "Awseome!"}; printAll(args);</java>
JavaScript
<javascript>function printAll() {
for (var i=0; i<arguments.length; i++) print(arguments[i])
} printAll(4, 3, 5, 6, 4, 3); printAll(4, 3, 5); printAll("Rosetta", "Code", "Is", "Awseome!");</javascript>
You can use the apply
method of a function to apply it to a list of arguments:
<javascript>args = ["Rosetta", "Code", "Is", "Awseome!"]
printAll.apply(null, args)</javascript>
Logo
UCB Logo allows four classes of arguments (in order):
- 0 or more required inputs (colon prefixed words)
- 0 or more optional inputs (two member lists: colon prefixed word with default value)
- an optional "rest" input (a list containing a colon prefixed word, set to the list of remaining arguments)
- ...with an optional default arity (a number)
to varargs [:args] foreach :args [print ?] end
(varargs "Mary "had "a "little "lamb) apply "varargs [Mary had a little lamb]
Perl
Functions in Perl 5 don't have argument lists. All arguments are stored in the array @_
anyway, so there is variable arguments by default.
<perl>sub print_all {
foreach (@_) { print "$_\n"; }
}</perl>
This function can be called with any number of arguments: <perl>print_all(4, 3, 5, 6, 4, 3); print_all(4, 3, 5); print_all("Rosetta", "Code", "Is", "Awseome!");</perl>
Since lists are flattened when placed in a list context, you can just pass an array in as an argument and all its elements will become separate arguments: <perl>@args = ("Rosetta", "Code", "Is", "Awseome!"); print_all(@args);</perl>
PHP
PHP 4 and above supports varargs. You can deal with the argument list using the func_num_args()
, func_get_arg()
, and func_get_args()
functions.
<php>function printAll() {
foreach (func_get_args() as $x) // first way echo "$x\n";
$numargs = func_num_args(); // second way for ($i = 0; $i < $numargs; $i++) echo func_get_arg($i), "\n";
} printAll(4, 3, 5, 6, 4, 3); printAll(4, 3, 5); printAll("Rosetta", "Code", "Is", "Awseome!");</php>
You can use the call_user_func_array
function to apply it to a list of arguments:
<php>$args = array("Rosetta", "Code", "Is", "Awseome!");
call_user_func_array('printAll', $args);</php>
Python
Putting * before an argument will take in any number of arguments and put them all in a tuple with the given name.
<python>def print_all(*things):
for x in things: print x</python>
This function can be called with any number of arguments: <python>print_all(4, 3, 5, 6, 4, 3) print_all(4, 3, 5) print_all("Rosetta", "Code", "Is", "Awseome!")</python>
You can use the same "*" syntax to apply the function to an existing list of arguments: <python>args = ["Rosetta", "Code", "Is", "Awseome!"] print_all(*args)</python>
Keyword arguments
Python also has keyword arguments were you can add arbitrary func(keyword1=value1, keyword2=value2 ...) keyword-value pairs when calling a function. This example shows both keyword arguments and positional arguments. The two calls to the function are equivalent. *alist spreads the members of the list to create positional arguments, and **adict does similar for the keyword/value pairs from the dictionary. <python>>>> def printargs(*positionalargs, **keywordargs): print "POSITIONAL ARGS:\n " + "\n ".join(repr(x) for x in positionalargs) print "KEYWORD ARGS:\n " + '\n '.join( "%r = %r" % (k,v) for k,v in keywordargs.iteritems())
>>> printargs(1,'a',1+0j, fee='fi', fo='fum')
POSITIONAL ARGS:
1 'a' (1+0j)
KEYWORD ARGS:
'fee' = 'fi' 'fo' = 'fum'
>>> alist = [1,'a',1+0j] >>> adict = {'fee':'fi', 'fo':'fum'} >>> printargs(*alist, **adict) POSITIONAL ARGS:
1 'a' (1+0j)
KEYWORD ARGS:
'fee' = 'fi' 'fo' = 'fum'
>>> </python>
RapidQ
RapidQ uses special keywords SUBI and FUNCTIONI for procedures and functions with variable number of parameters. Numeric parameters are accessed from array ParamVal and string parameters from array ParamStr$.
SUBI printAll (...) FOR i = 1 TO ParamValCount PRINT ParamVal(i) NEXT i FOR i = 1 TO ParamStrCount PRINT ParamStr$(i) NEXT i END SUBI printAll 4, 3, 5, 6, 4, 3 printAll 4, 3, 5 printAll "Rosetta", "Code", "Is", "Awseome!"
Ruby
The * is sometimes referred to as the "splat" in Ruby. def print_all(*things)
things.each { |x| puts x }
end
This function can be called with any number of arguments: print_all(4, 3, 5, 6, 4, 3) print_all(4, 3, 5) print_all("Rosetta", "Code", "Is", "Awseome!")
You can use the same "*" syntax to apply the function to an existing list of arguments: args = ["Rosetta", "Code", "Is", "Awseome!"] print_all(*args)
Scheme
Putting a dot before the last argument will take in any number of arguments and put them all in a list with the given name.
<scheme>(define (print-all . things)
(for-each (lambda (x) (display x) (newline)) things))</scheme>
Note that if you define the function anonymously using lambda
, and you want all the args to be collected in one list (i.e. you have no parameters before the parameter that collects everything), then you can just replace the parentheses altogether with that parameter, as if to say, let this be the argument list:
<scheme>(define print-all
(lambda things (for-each (lambda (x) (display x) (newline)) things)))</scheme>
This function can be called with any number of arguments: <scheme>(print-all 4 3 5 6 4 3) (print-all 4 3 5) (print-all "Rosetta" "Code" "Is" "Awseome!")</scheme>
The apply
function will apply the function to a list of arguments:
<scheme>(define args '("Rosetta" "Code" "Is" "Awseome!"))
(apply print-all args)</scheme>
V
In V, all the arguments are passed in stack, and the stack is freely accessible so var args is the default to any level of functions
Using a count as the indication of number of arguments to extract,
[myfn [zero? not] [swap puts pred] while ].
100 200 300 400 500 3 myfn
results in:
500 400 300