|
это сделано, скажем, в Паскале или в
Watcom C++. Однако кое-какая эмуляция локальных функций все же есть: если функ-
цию B() определить в теле функции A(), то она, хоть и не став локальной, все же
будет "видна" для программы ниже своего определения. Замечу для сравнения, что
похожая схема существует и в языке Perl. Впрочем, как показывает практика про-
граммирования на Си (вот уже 30 лет), это не такой уж серьезный недостаток.
В системе определения функций в PHP есть и еще один небольшой недочет, который
особенно неприятен тем, кто до этого программировал на других языках. Дело в
том,
что все переменные, которые объявляются и используются в функции, по умолчанию
локальны для этой функции. При этом существует только один (и при том довольно
некрасивый) способ объявления глобальных переменных — инструкция global (на
самом деле есть и еще один, через массив $GLOBALS, но об этом чуть позже). С
одной
стороны, это повышает надежность функций в смысле их независимости от основной
программы, а также гарантирует, что они случайно не изменят и не создадут
глобаль-
ных переменных. С другой стороны, разработчики PHP вполне могли бы предугадать
нужность инструкции, по которой все переменные функции становились бы по умол-
Часть III. Основы языка PHP 182
чанию глобальными — это существенно упростило бы программирование сложных
сценариев.
Пример функции
Как водится, сразу начну с примера. Предположим, нам необходимо в программе
очень часто находить в массиве-списке наибольший элемент, который в то же время
меньше какого-то, наперед заданного числа. А именно, нас интересует его номер в
массиве (если такого числа в массиве нет, то номер полагается равным -1).
Напишем
для этой цели функцию (такое описание называется определением функции, и оно,
конечно, должно быть единственным в пределах сценария).
Листинг 11.1. Пример функции
function GetMaxNum($arr, $max="")
{ // проходимся по всем элементам массива
for($i=0,$n=-1; $i$m) && ($max==="" || $arr[$i]<$max)) {
// сюда мы попадаем, когда очередной элемент больше текущего,
// либо же текущего элемента еще не существует (первый проход)
$m=$arr[$i]; // запоминаем текущий элемент
$n=$i; // запоминаем его номер
}
}
return $n;
}
В отличие от других языков программирования, функцию можно задавать не только в
определенном месте программы, но и прямо среди других операторов. Например,
вполне можно было бы поместить нашу функцию GetMaxNum() прямо в середину
кода, скажем, так:
echo "Программа...";
function GetMaxNum($arr,$max)
{ ... тело функции ...
}
echo "Программа продолжается!";
При таком подходе транслятор, дойдя до определения функции, просто прове-
рит его корректность и оттранслирует во внутреннее представление, но не бу-
Глава 11. Функции и области видимости 183
дет генерировать код для выполнения, а сразу переключится на следующие за
телом функции команды. Только потом, при вызове функции, интерпретатор
начнет исполнять ее команды...
Итак, мы создали функцию с именем GetMaxNum() и двумя параметрами, первый из
которых рассматривается ей как массив, а второй — как вещественное число.
На самом деле на этапе создания функции еще никаких предположений о ти-
пах параметров не строится. Однако попробуйте нашей функции вместо мас-
сива в первом аргументе передать число — интерпретатор "заругается", как
только выполнение дойдет до строчки с $arr[$i], и скажет, что "переменная
не является массивом".
Алгоритм работы функции таков: в цикле анализируем очередной элемент на пред-
мет "максимальности": если он больше текущего максимального элемента, но меньше
$max, он сам становится текущим максимумом, а его положение запоминается в $n.
(Обратите внимание, что в описании функции параметр $max задается в виде
$max="". Это означает, что если при вызове он будет опущен, то функция получит
пустую строку в $max.) После окончания цикла в $n окажется номер такого
элемента
(либо число -1, которое мы присвоили $n в начале). Его-то мы и возвращаем в
каче-
стве значения функции оператором return.
Ну вот, теперь в программе ниже описания функции можно написать:
$a=array(10,20,80,35,22,57);
$m=GetMaxNum($a,50); // теперь $m=3, т. е. $a[$m]=35
В действительности, поскольку фаза трансляции и исполнения в PHP разделе-
ны, мы можем применять вызовы функции еще до того, ка
|
|