TGViewer
Пых Пых @phpyh · 7.86K subscribers
Post #884 6.85K
Нюансы вариадических функций

Копаясь в статанализе в рамках проекта Typhoon, мы про каждую мелочь стараемся думать во всей полноте, чтобы не упустить даже очень редко используемые возможности PHP. Так мы периодически узнаём что-то новое.

Например, есть тип callable(<params>): <return type>. У параметров есть следующие модификаторы: = (со значением по умолчанию), ... (вариадический), & (передаётся по ссылке). Вопрос: как их можно сочетать?

1. Параметры, передаваемые по ссылке, очевидно, могут иметь значение по умолчанию.
2. Вариадические, очевидно, не могут иметь значения по умолчанию.
3. Могут ли вариадики передаваться по ссылке? Вот тут лично для меня уже неочевидно, потому что я вообще редко что-то передаю по ссылке.

Разбираемся. Вариадические функции добавил Никита Попов в далёком 2013 году (до этого все использовали func_get_args()), и вот что написано в RFC:

By-reference capture

The new syntax additionally adds support for capturing variadic arguments by-reference, something that was previously not possible in userland code. Only internal functions could make use of this via ZEND_ACC_PASS_REST_BY_REF.

This would allow implementing functions like sscanf() or mysqli_stmt::bind_param() in userland.

A by-reference capture of variadic arguments is indicated by a & before the ellipsis ....


Пробуем:


function increment(int &...$ints): void
{
foreach ($ints as &$int) {
++$int;
}
}

$a = 0;
$b = 100;

increment($a, $b);

var_dump($a, $b); // 1, 101


Получается, в параметрах типа callable возможны только два сочетания: &... и &=.

Кстати, обратите внимание: слово "опциональный" не является точным определением для = параметра. Опциональные параметры — это те, которые можно не передавать, к ним относятся не только параметры со значением по умолчанию, но и вариадические. Поэтому = однозначно определяется именно как параметр со значением по умолчанию (у нас в коде bool $hasDefault, а не $isOptional). Этот нюанс хорошо прослеживается в нативной рефлексии:


$reflection = new ReflectionParameter('increment', 'ints');

var_dump(
$reflection->isOptional(), // true
$reflection->isDefaultValueAvailable(), // false
);
  • 👍 31
  • 🔥 13
  • 😨 10
  • ❤ 5
More from @phpyh
  1. Sep 15, 2026Сейчас один человек с AI может выполнять работу целого IT-отдела. Только хуёво
  2. Sep 12, 2026Спасибо за заявки! Всем напишу в понедельник. Осталось 1 место.
  3. Sep 11, 2026Хардкорный курс асинхронного PHP https://hardcourse.ru/php/async
  4. Sep 11, 2026Ещё полчасика надо — сайт готов, расписываю программу! 🙏
  5. Sep 10, 2026Краткое содержание: завтра в 12:00 открываю набор на Хардкорный курс асинхронного PHP с уч…
  6. Sep 10, 2026Post #1011
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →