views:

391

answers:

9

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]
A: 

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.

Yuval F
A: 

Well, in javascript you don't have to specify what variables you expect. You can use the arguments property of the function to access them:

function func() {
  if(!arguments.length) return;
  var first = arguments[0];
  var middle = Array.prototype.slice.call(arguments,1,arguments.length-1)
  var last = arguments[arguments.length-1];
  return middle;
}


func(1,2,3,4,5); // returns 2,3,4
some
A: 

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
}
jmucchiello
+2  A: 

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
Artelius
LOL! Didn't see this one coming
Damir Zekić
+2  A: 

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);
}
Johannes Schaub - litb
"the next c++"?
Claudiu
yeah, as it happened, C++ got a version :) looks like the new one will be released 2010. You can play with initializer lists with the current gcc trunk, which already supports them (at least to that agree that you can compile and use the code above) :)
Johannes Schaub - litb
I think in this example b is just one argument. and in function g, f is called with three arguments: 1, {2,3,4,5}, and 2.
yeah, that is teh trickery. it's not really 6 arguments
Johannes Schaub - litb
+1  A: 

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

Python docs http://diveintopython.org/power_of_introspection/optional_arguments.html

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

Stobor
+1  A: 

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.

Jörg W Mittag
Oh my, the Ruby syntax highlighting is *exceptionally* crappy, even for prettify.js.
Jörg W Mittag
iinteresting, thanks!
Claudiu
A: 

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
>
Gregg Lind
A: 

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!