Question

Python, C++, Scheme, and others all let you define functions that take a variable number of arguments at the end of the argument list...

def function(a, b, *args):
    #etc...

...that can be called as followed:

function(1, 2)
function(1, 2, 5, 6, 7, 8)

etc... Are there any languages that allow you to do variadic functions with the argument list somewhere else? Something like this:

def function(int a, string... args, int theend) {...}

With all of these valid:

function(1, 2)
function(1, "a", 3)
function(1, "b", "c", 4)

Also, what about optional arguments anywhere in the argument list?

def function(int a, int? b, int c, int... d) {}

function(1, 2) //a=1, c=2, b=undefined/null/something, d=[]
function(1,2,3) //a=1, b=2, c=3,d=[]
function(1,2,3,4,5) //a=1, b=2, c=3, d=[4,5]
Was it helpful?

Solution

Future versions of Ruby (1.9 and up, Ruby 1.9 is scheduled to released at the end of January, 2009) can do this.

It is however not always obvious which value gets bound to which parameter.

This is what Ruby 1.9 accepts:

0 or more mandatory arguments followed by 0 or more optional arguments followed by 0 or more mandatory arguments followed by rest arguments followed by 0 or more mandatory arguments.

Example:

def meth mand1, opt1 = :def1, o2 = :d2, *args, m2, m3
  puts %w[mand1 opt1 o2 m2 args m3].inject('') { |s, arg|
    s << "#{arg} = #{(eval arg).inspect}, "
  }.gsub /, $/, ''
end

meth :arg1, :a2, :a3
# => mand1 = :arg1, opt1 = :def1, o2 = :d2, m2 = :a2, args = [], m3 = :a3
meth :arg1, :a2, :a3, :a4
# => mand1 = :arg1, opt1 = :a2, o2 = :d2, m2 = :a3, args = [], m3 = :a4
meth :arg1, :a2, :a3, :a4, :a5
# => mand1 = :arg1, opt1 = :a2, o2 = :a3, m2 = :a4, args = [], m3 = :a5
meth :arg1, :a2, :a3, :a4, :a5, :a6
# => mand1 = :arg1, opt1 = :a2, o2 = :a3, m2 = :a5, args = [:a4], m3 = :a6
meth :arg1, :a2, :a3, :a4, :a5, :a6, :a7
# => mand1 = :arg1, opt1 = :a2, o2 = :a3, m2 = :a6, args = [:a4, :a5], m3 = :a7

As you can see, mandatory arguments are bound first, from both the left and the right. Then optional arguments get bound and if any arguments are left over, they get bundled up in an array and bound to the rest argument.

OTHER TIPS

The next C++ can do that with this syntax:

void f(int a, std::initializer_list<int> b, int c) {
    // b.begin(), b.end(), b.size() allow to access them
}

void g() { 
    f(1, { 2, 3, 4, 5 }, 2);
}

BASIC has had this for ages.

For instance:

LOCATE [row%] [,[column%] [,[cursor%] [,start% [,stop%]]]]

This command sets the position (row%, column%) of the cursor, as well as specifying the cursor size (start%, stop%) and whether it is actually visible (cursor%). Here, everything in square brackets can be omitted, and if it is, that property is not changed.

A usage example:

LOCATE , 5

to change to column 5, or

LOCATE 1, , 0

to move to the first line and make the cursor invisible.

Another command where this is seen is the PUT command for writing to files. If the middle argument (the file seek position) is omitted then writing occurs just after the previous write.

Importantly, argument omission is only seen in built-in statements, and not user-defined procedures and functions.

In terms of implementation, this is what the Microsoft Basic Compiler (BC) seems to do for a call to LOCATE:

  1. For each argument:
    • if an argument is omitted, push 0
    • if an argument is supplied, push 1, and then push the actual value
  2. Push the argument count
  3. Call the library function

Several languages (perl, python, many others) can do named arguments, which are akin to doing optional arguments anywhere in the parameter list... (The named parameters can appear in any order, and any of them can be made optional...) They're not strictly the same, but they're close...

Not sure about varargs, though they can usually be replaced with an array/hash/list object...

Lisp's keyword parameters may be what you are looking for. I think there is a similar arrangement in Ruby. See also Lisp's function parameters overview.

I suppose PHP counts. You can do this to simulate what you are looking for. Personally, I think that would be confusing though.

function foo() {
    $args = func_get_args(); // returns an array of args
}

R (the statistical language) has it as well, and it can be in the middle of the list, but there are subtle semantics.

http://cran.r-project.org/doc/manuals/R-intro.html#The-three-dots-argument

> f1 <- function(x,...,y) {  return(x+y) }
> f1(1,2)
Error in f1(1, 2) : argument "y" is missing, with no default
> f1(1,y=2)
[1] 3
> f1 <- function(x,...,y) {  return(x+y) }
> f1(1,2)
Error in f1(1, 2) : argument "y" is missing, with no default
> f1(1,y=2)
[1] 3
> 

It is called Rest Arguments and it can be done at least in C++ and Java. Google "Rest Arguments" and you will find a lot of data on the subject with some examples like functions that will pass numbers and return an average of the numbers input, maybe the minimum or maximum of all numbers passed. As you can see, there are a lot of uses for such features, I used it in code for inputing data in MYSQL so when I want to add a row, I just add the Table name as the first string and the rest are all column names and then their data without having to sit there and manually do it over and over again. Good Luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top