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