views:

363

answers:

6

In all programming languages supporting optional parameters that I have seen there is a imitation that the optional parameters must appear at the end of the declaration. No required parameters may be included after an optional item. What is the reason for that ? I guess it can be compiler/interpreter requirement.

+12  A: 

Well, if they were at the front, how would you detect when they've stopped being supplied? The only way would be if the variable type was different after the optional parameters. Bit of a weird requirement, so it makes sense that you just force them to be last (save the trouble of complex rules for detecting the "final" optional parameter).

Besides, it's the most natural way to do it when calling the function.

Noon Silk
Yea it looks so obvious now :). Thank you.
Incognito
@Incognito: it works just fine in Ruby. If there are mandatory parameters after the optional ones, then the mandatory arguments are taken from the end of the argument list. Everything left over are the optional arguments. See http://StackOverflow.Com/questions/2896106/why-optional-parameters-must-appear-at-the-end-of-the-declaration/2900474/#2900474 for an example.
Jörg W Mittag
A: 

Just guessing in the wild: It maybe has something to do with calling conventions (e.g. parameters are pushed on the stack left to right, optional parameters are simply left out in case they were not specified).

Johannes Rudolph
I'd doubt that, I think the caller will just push the default values instead.
tstenner
A: 

Java and C# don't have named parameters so you can't do:

myfunction(param1='Meh', optionalParam=2)

You have to do:

myfunction('Meh', 2)

Otherwise

myFunction(2, 'Meh')

Is ambiguous. How is the compiler supposed to know that you meant 2 to be in the optional parameter set?

cyborg
C# 4.0 has named parameters.
Incognito
A: 

Optional parameters at the end allow you to stop specifying parameters at some point, e.g.

void Test(int a, optional int b = 0, optional int c = 0) { ... } 

Test(3);

If you make c a required parameter, you'd have to use syntaxes like this:

Test(3, , 2);
Test(a := 3, c := 2);

The advantage of an optional parameter is that it can be treated as if it wasn't there. If the optional parameters are in the middle of the parameter list, this is not possible without "counting commas" or using an overly verbose syntax.

Heinzi
This works just fine in Ruby. Mandatory parameters at the beginning of the parameter list are bound from left-to-right from the beginning of the argument list. Mandatory parameters at the end of the parameter list are bound from right-to-left from the end of the argument list. Optional parameters are bound left-to-right from the beginning of the remaining argument list. All arguments left over are bound to rest arguments. Not supplying a mandatory argument or supplying more than `num_mandatory + num_optional` arguments when there is no rest parameter is an error.
Jörg W Mittag
+1  A: 

Consider a declaration like:

int foo(float a, int b=0, int c=0, float d);

(notice how I've defined defult parameters in the middle of the list) which is subsequently called like

foo(0.0,1,2.0)

What is the call? In particular has b or c been omitted?

Compiler designers can get around this by using named parameters

foo(a=0,c=0,d=2.0)

a feature available in python for instance.

dmckee
That feature is also available in C#: foo(a: 0, c: 0, d: 2.0). Problem is what to do when positional calls are made.
configurator
This works just fine in Ruby. Mandatory parameters at the beginning of the parameter list are bound from left-to-right from the beginning of the argument list. Mandatory parameters at the end of the parameter list are bound from right-to-left from the end of the argument list. Optional parameters are bound left-to-right from the beginning of the remaining argument list. All arguments left over are bound to rest arguments. Not supplying a mandatory argument or supplying more than `num_mandatory + num_optional` arguments when there is no rest parameter is an error.
Jörg W Mittag
In your specific example, `a` would be bound to `0.0`, `d` to `2.0`, `b` to `1` and `c` would get its default value of `0`.
Jörg W Mittag
@ Jore In the example above, if I want to pass 1 to c and make b use it default value, what should I do? It looks like in Ruby 'b' is only partial optional...
Bolu
+2  A: 

This is just an arbitrary rule that the designers of those specific languages made. There is absolutely no technical reason why that restriction should be there.

It works just fine in Ruby:

def foo(m1, m2, o1='o1', o2='o2', *rest, m3, m4)
  return m1, m2, o1, o2, rest, m3, m4
end

foo(1, 2, 3, 4)
# => [1, 2, 'o1', 'o2', [], 3, 4]

foo(1, 2, 3, 4, 5)
# => [1, 2, 3, 'o2', [], 4, 5]

foo(1, 2, 3, 4, 5, 6)
# => [1, 2, 3, 4, [], 5, 6]

foo(1, 2, 3, 4, 5, 6, 7)
# => [1, 2, 3, 4, [5], 6, 7]

foo(1, 2, 3, 4, 5, 6, 7, 8)
# => [1, 2, 3, 4, [5, 6], 7, 8]

All mandatory arguments must be supplied:

foo(1, 2, 3)
# => ArgumentError: wrong number of arguments (3 for 4)

Without the rest parameter, supplying more than number_of_mandatory + number_of_optional arguments is an error:

def bar(m1, m2, o1='o1', o2='o2',  m3, m4)
  return m1, m2, o1, o2, m3, m4
end

bar(1, 2, 3, 4, 5, 6, 7)
# => ArgumentError: wrong number of arguments (7 for 6)

Mandatory parameters at the beginning of the parameter list are bound from left-to-right from the beginning of the argument list. Mandatory parameters at the end of the parameter list are bound from right-to-left from the end of the argument list. Optional parameters are bound left-to-right from the beginning of the remaining argument list. All arguments left over are bound to rest arguments.

Jörg W Mittag
Obviously correct---the more so as you have a working example to show. But I will quibble to the extent that c-like languages are mostly built out of simple rules, and the ruby way is long-winded: it would be a big surprise in c, and at least a small one in c++.
dmckee
@dmckee: The only C-like language I know that has optional arguments would be C#, but its rules are massively complicated due to complex interactions between optional arguments and arity-based overloading. I find both of them *at least* similarly complicated, maybe C# even a little bit more.
Jörg W Mittag