Variadic function

From Rosetta Code
Task
Variadic function
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.

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>

  1. 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>

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.

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.)

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.

Io

printAll := method(call message arguments foreach(println))

Java

Works with: Java version 1.5+

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>

Works with: UCB Logo

UCB Logo allows four classes of arguments (in order):

  1. 0 or more required inputs (colon prefixed words)
  2. 0 or more optional inputs (two member lists: colon prefixed word with default value)
  3. an optional "rest" input (a list containing a colon prefixed word, set to the list of remaining arguments)
  4. ...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>

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