在我见过的所有支持可选参数的编程语言中,都有一个模仿,即可选参数必须出现在声明的末尾。可选项目后不得包含必填参数。这是什么原因?我想这可能是编译器/解释器的要求。
6 回答
好吧,如果他们在前线,你如何发现他们什么时候停止供应?唯一的方法是在可选参数之后变量类型不同。有点奇怪的要求,所以你只是强迫它们放在最后是有道理的(省去检测“最终”可选参数的复杂规则的麻烦)。
此外,这是调用函数时最自然的方式。
这只是那些特定语言的设计者制定的任意规则。绝对没有技术上的理由应该存在这种限制。
它在 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]
必须提供所有强制参数:
foo(1, 2, 3)
# => ArgumentError: wrong number of arguments (3 for 4)
如果没有其余参数,则提供超过 number_of_mandatory + number_of_optional 参数是错误的:
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)
参数列表开头的强制参数从参数列表的开头从左到右绑定。参数列表末尾的强制参数从参数列表的末尾从右到左绑定。可选参数从剩余参数列表的开头从左到右绑定。剩下的所有参数都必须是其余参数。
考虑如下声明:
int foo(float a, int b=0, int c=0, float d);
(注意我是如何在列表中间定义默认参数的),随后被称为
foo(0.0,1,2.0)
电话是什么?特别是已经b
或被c
省略了?
编译器设计者可以通过使用命名参数来解决这个问题
foo(a=0,c=0,d=2.0)
例如,python 中可用的功能。
最后的可选参数允许您在某些时候停止指定参数,例如
void Test(int a, optional int b = 0, optional int c = 0) { ... }
Test(3);
如果您创建c
一个必需的参数,则必须使用如下语法:
Test(3, , 2);
Test(a := 3, c := 2);
可选参数的优点是可以将其视为不存在。如果可选参数位于参数列表的中间,则如果不使用“计数逗号”或使用过于冗长的语法,这是不可能的。
只是在野外猜测:它可能与调用约定有关(例如,参数从左到右压入堆栈,可选参数被简单地省略以防它们未指定)。
Java 和 C# 没有命名参数,所以你不能这样做:
myfunction(param1='Meh', optionalParam=2)
你所要做的:
myfunction('Meh', 2)
否则
myFunction(2, 'Meh')
是模棱两可的。编译器应该如何知道您的意思是 2 在可选参数集中?