为什么可选参数必须出现在声明的末尾

在所有支持可选参数的编程语言中,我都看到可选参数必须出现在声明的末尾。 可选项目后可能不包含必需参数。 这是什么原因? 我想这可能是编译器/解释器的要求。

好吧,如果他们在前面,你会怎么检测他们什么时候停止供应? 唯一的方法是可选参数之后变量类型不同。 有点奇怪的要求,所以你只需强制它们是最后一个是有道理的(省去​​了检测“最终”可选参数的复杂规则的麻烦)。

此外,调用函数时,这是最自然的方式。

这只是这些特定语言的设计者所做的任意规则。 绝对没有技术上的理由为什么应该存在这种限制。

它在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) 

如果没有rest参数,则提供多个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); 

(注意我是如何在列表中间定义defult参数的),随后调用它们

 foo(0.0,1,2.0) 

什么叫? 特别是bc被省略了吗?

编译器设计者可以通过使用命名参数来解决这个问题

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

例如,python中提供的一个function。

只是猜测:它可能与调用约定有关(例如,参数从左到右被推到堆栈中,如果未指定可选参数,则简单地省略它们)。

最后的可选参数允许您在某个时刻停止指定参数,例如

 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在可选参数集中?