Во всех языках программирования, поддерживающих необязательные параметры, которые я видел, есть имитация того, что необязательные параметры должны появляться в конце объявления. Никакие обязательные параметры не могут быть включены после необязательного элемента. В чем причина этого? Я предполагаю, что это может быть требование компилятора/интерпретатора.
Почему необязательные параметры должны стоять в конце объявления
Ответы (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)
Без параметра rest предоставление большего количества аргументов, чем число_обязательных + число_необязательных, является ошибкой:
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.
num_mandatory + num_optional
аргументов при отсутствии остальных параметров является ошибкой.
- person Jörg W Mittag; 25.05.2010
a
будет привязан к 0.0
, d
к 2.0
, b
к 1
, а c
получит значение по умолчанию 0
.
- person Jörg W Mittag; 25.05.2010
Необязательные параметры в конце позволяют вам прекратить указывать параметры в какой-то момент, например.
void Test(int a, optional int b = 0, optional int c = 0) { ... }
Test(3);
Если вы сделаете c
обязательным параметром, вам придется использовать такой синтаксис:
Test(3, , 2);
Test(a := 3, c := 2);
Преимущество необязательного параметра в том, что его можно рассматривать так, как если бы его не было. Если необязательные параметры находятся в середине списка параметров, это невозможно без «подсчета запятых» или использования слишком подробного синтаксиса.
num_mandatory + num_optional
аргументов при отсутствии остальных параметров является ошибкой.
- person Jörg W Mittag; 25.05.2010
Просто предполагаю: возможно, это как-то связано с соглашениями о вызовах (например, параметры помещаются в стек слева направо, необязательные параметры просто не учитываются, если они не были указаны).
Java и С# не имеют именованных параметров, поэтому вы не можете:
myfunction(param1='Meh', optionalParam=2)
Ты должен сделать:
myfunction('Meh', 2)
Иначе
myFunction(2, 'Meh')
Неоднозначно. Как компилятор должен узнать, что вы имели в виду 2 в необязательном наборе параметров?