Когда-то, давным-давно, когда я еще учился программировать на Паскале, мне пришлось на лабораторке переделывать одну собственную функцию — нужно было в результатах возвращать не просто число, а число и строку. Как было бы хорошо, подумал я тогда, если бы в результате можно было возвращать множество переменных, как это сделано для входных параметров. Подумал, вздохнул и начал создавать структуру для передачи обратно в вызывающую функцию двух параметров за раз.
В следующий раз о входных аргументах я задумался, когда впервые столкнулся с необходимостью разбора параметров командной строки в С/C++. Ну, помните это классическое:
int main(int argc, char* argv[])
Всего два входных параметра функции, но в них уложены все возможные комбинации CLI-параметров программы. Да, за универсальность вызова пришлось заплатить сложностью парсинга, но вариантов решить задачу кардинально по-другому как бы и нет.
Следующий раз задуматься о входных/выходных аргументах пришлось при анализе promises:
get('story').then(fnSuccess1).then(fnSuccess2). ... .catch(fnError);
В цепочке промисов выходные параметры одной функции передаются на вход другой (первым аргументом), видоизменяются и передаются далее, далее, далее… Получалось так, что для подобного конвейера важна была именно универсализация: один выходной аргумент — один входной аргумент.
Дальше — больше. В JavaScript нет перегрузки функций, поэтому там никого не парит такой код:
function sayHi() {
for (var i = 0; i < arguments.length; i++) {
alert( "Привет, " + arguments[i] );
}
}
sayHi("Винни", "Пятачок"); // 'Привет, Винни', 'Привет, Пятачок'
После долгого общения с Java mistress такой код выглядит, словно обкуренный хиппи-шестидесятник рядом с офицером спецназа на боевом задании — "У этой функции вообще нет аргументов? Ну и что, расслабься, чувак! Давай-ка я скручу тебе arguments… На вот, дерни, и сколько бы тебе там чего не передали — все увидишь".
Более того, в JavaScript'е я есть такая функция, как apply:
fun.apply(thisArg[, argsArray])
назначение которой — применить функцию в заданном контексте с заданными аргументами. Здесь тоже никого не волнует, сколько входных аргументов ожидает увидеть сама функция (или ее автор) — задавай сколько хочешь.
В моей PHP-практике был случай, когда в стороннем модуле при перегрузке базового метода поменяли местами два аргумента (восьмой и деятый, или даже девятый и десятый — не суть важно).
public function doGood($a, $b, $c, $d, $e, $f, $g, %h, $i, $j) {}
public function doGood($a, $b, $c, $d, $e, $f, $g, %h, $j, $i) {
parent::doGood($a, $b, $c, $d, $e, $f, $g, %h, $i, $j);
}
Для простых случаев их значения были равны, поэтому "от перемены мест слагаемых сумма не изменилась", у меня была конфигурация посложнее, поэтому бага и вылезла (вернее, я ее долго отладчиком выщемлял). Я после того отладочного дайва как-то более тепло, что ли, смотрю на конструкции типа:
func(opts)
или
Response resp = service.call(req);
Кстати, последняя конструкция у меня прочно ассоциируется с BDSM BPMS — был как-то интересный опыт привязки intalio к web-приложению. Каждый процесс состоял из отдельных операций, которые имплементировались web-сервисами по схеме "y = f(x)", где x и y сводились к XML-документам (иногда простым, иногда не очень), а "программирование процессов мышкой" к маппингу элементов игреков одних сервисов на элементы иксов других сервисов.
Возможно поэтому в своей текущей практике (PHP) я попытался свести некоторые группы функций к схеме "y = f(x)". В JavaScript это делается легко и приятно.
Было
function showWarning(width, height, title, contents) {
var width = width || 200; // если не указана width, то width = 200
var height = height || 100; // если нет height, то height = 100
var title = title || "Предупреждение";
var contents = contents || "Ничего серьезного.";
//...
}
Стало:
function showWarning(opts) {
var opts = opts || {}; // если отсутствуют входные параметры
var width = opts.width || 200; // если не указана width, то width = 200
var height = opts.height || 100; // если нет height, то height = 100
var title = opts.title || "Предупреждение";
var contents = opts.contents|| "Ничего серьезного.";
//...
}
В PHP приходится платить разработкой структуры входных/выходных аргументов в отдельных классах. В основном получается муторно, но иногда — весело.
К чему я это все? А к тому, что сейчас я уже не думаю, что было бы хорошо возвращать множество параметров вместо одного "y", а задумываюсь над тем, в каких случаях было бы хорошо иметь на входе всего один "x".