Вызов функций в аргументах функций

Продолжаем тему выражений. Как вы помните, вызов функции — выражение, а значит мы можем положить вызов функции в вызов функции (…в вызов функции в вызов функции в вызов… а-а-а!).

<?php

$number = 100.234203;
$result = round(abs($number), 2);

Мы вызываем функцию round() и передаем ей два аргумента:

  • результат вызова функции abs() с аргументом $number
  • число 2.

Можно сделать то же самое, но с промежуточными шагами:

<?php

$number = 100.234203;
$module = abs($number);
$result = round($module, 2);

Какой вариант предпочтительнее? Если вычисление совсем простое и неглубокое (не больше одного вложения функции), то можно смело вкладывать вызов в вызов. В остальных ситуациях предпочтительно разбивать вызовы на промежуточные вычисления.

Причины всё те же. Чтение такого кода значительно легче. Во-первых, промежуточные переменные своими названиями отражают суть операций. Во-вторых, такой код легче отлаживать, а промежуточные данные проще исследовать. И в-третьих, глубокие вложенные вызовы сложно читать. В продвинутых языках подобная проблема решается механизмом типа композиции функций, но в PHP, к сожалению, подобного нет.

Давайте вглянем на код и попробуем ответить на вопрос: что в каком порядке будет вычисляться?

<?php

$number = -100.234203;
$result = round(abs($number), round(2.43));

PHP, как и большинство традиционных языков, является языком с жадными вычислениями (в других языках бывают ленивые вычисления). PHP пытается вычислить сначала максимально глубокий уровень вызова, затем менее глубокий, и так двигается снизу вверх пока не вычислит всё.

В нашем примере сначала будут вычислены аргументы, а затем получившиеся данные попадут в вызов round.

Ситуация с вложенными вызовами функций часто вводит новичков в ступор. Здесь нет никакой магии, нужно просто чуть больше тренировок. Хорошее упражнение — расписывать процесс по шагам на бумажке, симулируя действия компьютера. Вот так:

  1. $result = round(abs($number), round(2.43));
  2. $result = round(100.234203, round(2.43));
  3. $result = round(100.234203, 2);
  4. $result = 100.23;

Задание

Для построения генеалогического дерева семьи Старков Сэм написал функцию getParentFor(), которая возвращает имя родителя, если передать ей первым параметром полное имя ребенка. Вторым параметром функция принимает строчку $father или $mother. Так функция понимает, кого из родителей возвращать. По умолчанию параметр равен $mother. То есть, если нужно узнать имя матери, то можно не передавать специально $mother, а передать лишь один параметр — имя ребенка.

Напишите программу, которая выводит на экран имя деда Джоффри по материнской линии. Полное имя Джоффри на английском: Joffrey Baratheon.

Пример использования функции getParentFor:

<?php

$mother = getParentFor('Joffrey Baratheon');
print_r($mother); // => Cersei Lannister

Советы


Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном cообществе
Упражнение доступно только авторизованным пользователям.

Пожалуйста, авторизуйтесь, это необходимо для отслеживания прогресса выполнения уроков. Если у вас ещё нет учётной записи, то сейчас самое время создать аккаунт.