Функции в PHP.
Смысл и назначение.
Функции в PHP выполняют ту же роль, что и в любом языке программирования. Можно выделить несколько аспектов и порождаемых ими преимуществ использования функций.
1. Функции выполняют роль системных или пользовательских подпрограмм, т.е. автономных алгоритмов, которые можно вызвать из любого места основного кода.
2. Функции, заключая в себе некий обобщенный блок логики, улучшют читабельность и архитектуру кода. Т.к. отпадает необходимость вставлять этот блок в места необходимого применения, повторяя одинаковые участки и увеличивая (иногда многократно) сплошное полотно кода.
Функция может принимать некоторые значения в качестве параметров, требуемых ей для работы, и возвращать результат работы. Т.к. вызов функции - это выражение, то и результат её работы, как и любого выражения , может быть присвоен в переменную, либо непосредственно передан в другую функцию.
Синтаксис.
Объявление. Функция объявляется ключевым словом "function". Затем следует имя функции. после имени - круглые скобки (с перечислением параметров), в виде переменных через запятую. Если параметров нет, скобки остаются пустыми. После круглых скобок следут блок с кодом функции в {фигурных кавычках}.
К примеру, классический helloworld, выводимый с помощью функции, выглядит так:
Данная функция ничего не возвращает и не принимает никаких параметров.
Если результатом работы функции должно быть некое итоговое значение, оно возвращается ключевым словом "return". Оно же является точкой выхода из тела функции.
Применительно к предыдущему примеру, это будет выглядеть так:
Вызов функции осуществляется указанием её имени с последующими круглыми скобками.
Параметры функций.
Когда нам необходимо описать функцию, принимающую для своей работы некоторые параметры (в терминах алгебры - аргументов), мы указываем имена параметров в круглых скобках после имени функции, через запятую. В теле функции параметры ведут себя так же, как переменные.
Необходимо учитывать нюанс, связанный к присваиванием значений в PHP. Когда мы передаем параметр в функцию, существует два варианта оперирования с параметрами. Если это скалярное значение (число, строка, булевское), то происходит копирование значения в параметр. Но, если передаваемый аргумент функции - объект, то создается ссылка на объект, сам же объект не копируется. С передачей же массивов ситуация несколько неоднозначная, как и с присваиванием их переменным.
Для гарантированной передачи аргумента по ссылке используется унарный оператор амперсанда.
Параметры по умолчанию.
Использование дефолтных параметров бывает оправданно в ситуации, когда одним из типичный вариантов использования функции оказывается достаточно частый вызов её с некоторым постоянным значением параметра. Особенно часто это бывают параметры булевского или целочисленного типа, которые отвечают за один из типичных вариантов выполнения функции.
Для использования параметров по умолчанию используется синтаксис, аналогичный присваиванию значения переменной.
Статические переменные в функциях.
Статические переменный - это не совсем обычные элементы. В отличие от прочих объектов, создаваемых внутри пространства функции заново каждый раз при её запуске, статические переменные инициалируются прописанным в коде состоянием только при первом запуске. При всех последующих запусках в начале работы функции статическая переменная хранит то значение, которое было в ней в момент окончания предыдущего запуска. Строка инициализации словно пропускается, а вместо неё переменная инициализируется своим "старым" значением, полученным в результате предыдущего вызова.
Отсюда немаловажный нюанс - статические переменные могут инициализироваться только значениями, но не выражением.
Статические переменные объявляются при помощи ключевого слова "static" перед именем переменной.
Результат работы кода:
Лямбда-функции.
С версии 5.3 в PHP стали доступны анонимные функции (лямбда-функции, замыкания). Такая функция создается подобно обычной функции, но без имени. результат выражения, описывающего функцию, можно присвоить переменной. После чего использовать её как обычную функцию, или оперировать ею как объектом.
Как и в классических функциональных языках, лямбда-функции могут замыкать на себя родительский контекст, откуда и название "замыкания".
Замыкание анонимной функции на локальный контекст, в котором она была объявлена, совершается при помощи ключевого слова "use". Переменные, перечисленные в круглых скобках после "use" становятся доступны внутри анонимной функции и после выхода за пределы родительского пространства имен. Например, в случае возвращения анонимной функции как результата работы родительской функции. Ниже - пример возвращаемой анонимной функции, которая при дальнейшем вызове использует для сравнения длину массива, сохраненную в переменной $num.
Результат:
Стандартные (встроенные) функции PHP.
Несомненно, такой мощный инструмент, как функции, не мог быть обойден разработчиками PHP при разработке возможностей языка. Поэтому PHP содержит огромное количество функций для самых разных задач, начиная определением типа значения переменной и обработкой строк и заканчивая сетевыми запросами и работой с файловой системой. Учитывая количество, нет смысла полностью их описывать, или даже перечислять. Посмотреть и почитать описание можно на php.net .
Функции для работы с функциями.
Для более гибкого оперирования с функциями, PHP предоставляет нам набор специальных встроенных функций. Вот некоторые из них:
call_user_func
function_exists
Функции с переменным количеством параметров.
Еще одна из функций для функций - func_get_args. Данная функция позволяет получить список переданных в текущую функцию параметров. Это открывает разработчику возможность создавать функции с переменным количеством параметров. Что еще более увеличивает гибкость построения кода, по сравнению даже с предопределенным параметрами.
Как мы видим, функции - мощный и удобный инструмент для структурирования и оптимизации кода. Следующий этап на этом пути - классы и объектно-ориентированное программирование.
PS. Бонус для дотошного читателя :)
Возник вопрос о сроке жизни контекста, окружающего лямбда-функцию.
И можно ли привязать несколько функций на один контекст.
При некотором рассмотрении выясняется нюанс, очевидный не сразу.
Во-первых, мы не можем просто так вернуть несколько методов, т.к. возвращается-то один результат.
Во-вторых, в каждый вызов функции, порождающей лямбду, создается новый контекст, переменные которого и становятся доступны анонимной функции.
В итоге получилось вот такое решение, больше похожее на некий странный ООП. Странный в традициях PHP, но вполне имеющий место в JavaScript, например.
Вот это решение.
PPS. По некотором размышлении пришла мысль, что в ходе чтения статей неподготовленным кодером использование StdClass в последнем примере может оказаться непонятным. Посему пример имеет альтернативную реализацию, см. ниже. Результат выполнения тот же.
Не-объектная реализация мульти-лямбдового контекста.
Смысл и назначение.
Функции в PHP выполняют ту же роль, что и в любом языке программирования. Можно выделить несколько аспектов и порождаемых ими преимуществ использования функций.
1. Функции выполняют роль системных или пользовательских подпрограмм, т.е. автономных алгоритмов, которые можно вызвать из любого места основного кода.
2. Функции, заключая в себе некий обобщенный блок логики, улучшют читабельность и архитектуру кода. Т.к. отпадает необходимость вставлять этот блок в места необходимого применения, повторяя одинаковые участки и увеличивая (иногда многократно) сплошное полотно кода.
Функция может принимать некоторые значения в качестве параметров, требуемых ей для работы, и возвращать результат работы. Т.к. вызов функции - это выражение, то и результат её работы, как и любого выражения , может быть присвоен в переменную, либо непосредственно передан в другую функцию.
Синтаксис.
Объявление. Функция объявляется ключевым словом "function". Затем следует имя функции. после имени - круглые скобки (с перечислением параметров), в виде переменных через запятую. Если параметров нет, скобки остаются пустыми. После круглых скобок следут блок с кодом функции в {фигурных кавычках}.
К примеру, классический helloworld, выводимый с помощью функции, выглядит так:
<?php function hello(){ echo "Hello, world!"; }
Данная функция ничего не возвращает и не принимает никаких параметров.
Если результатом работы функции должно быть некое итоговое значение, оно возвращается ключевым словом "return". Оно же является точкой выхода из тела функции.
Применительно к предыдущему примеру, это будет выглядеть так:
<?php function hello(){ $result = "Hello, world!"; return $result; }
Вызов функции осуществляется указанием её имени с последующими круглыми скобками.
<?php function hello(){ $result = "Hello, world!"; return $result; } print hello(); // выведет: Hello, world!
Параметры функций.
Когда нам необходимо описать функцию, принимающую для своей работы некоторые параметры (в терминах алгебры - аргументов), мы указываем имена параметров в круглых скобках после имени функции, через запятую. В теле функции параметры ведут себя так же, как переменные.
<?php function hello($somebody){ $result = "Hello, $somebody"; return $result; } print hello("Kitty"); // : Hello, Kitty!
Необходимо учитывать нюанс, связанный к присваиванием значений в PHP. Когда мы передаем параметр в функцию, существует два варианта оперирования с параметрами. Если это скалярное значение (число, строка, булевское), то происходит копирование значения в параметр. Но, если передаваемый аргумент функции - объект, то создается ссылка на объект, сам же объект не копируется. С передачей же массивов ситуация несколько неоднозначная, как и с присваиванием их переменным.
Для гарантированной передачи аргумента по ссылке используется унарный оператор амперсанда.
<?php function hello(& $somebody){ $result = "Hello, $somebody"; return $result; } print hello("Kitty"); // : Hello, Kitty!
Параметры по умолчанию.
Использование дефолтных параметров бывает оправданно в ситуации, когда одним из типичный вариантов использования функции оказывается достаточно частый вызов её с некоторым постоянным значением параметра. Особенно часто это бывают параметры булевского или целочисленного типа, которые отвечают за один из типичных вариантов выполнения функции.
Для использования параметров по умолчанию используется синтаксис, аналогичный присваиванию значения переменной.
<?php function hello($somebody = "world"){ $result = "Hello, $somebody"; return $result; } print hello("Kitty"); // : Hello, Kitty! print hello(); // Hello, world!
Статические переменные в функциях.
Статические переменный - это не совсем обычные элементы. В отличие от прочих объектов, создаваемых внутри пространства функции заново каждый раз при её запуске, статические переменные инициалируются прописанным в коде состоянием только при первом запуске. При всех последующих запусках в начале работы функции статическая переменная хранит то значение, которое было в ней в момент окончания предыдущего запуска. Строка инициализации словно пропускается, а вместо неё переменная инициализируется своим "старым" значением, полученным в результате предыдущего вызова.
Отсюда немаловажный нюанс - статические переменные могут инициализироваться только значениями, но не выражением.
Статические переменные объявляются при помощи ключевого слова "static" перед именем переменной.
<?php function foo(){ static $x = 0; $x++; print " x = $x \n"; } for($i=0; $i<10; ++$i){ foo(); }
Результат работы кода:
x = 1 ; x = 2 ; x = 3 ; x = 4 ; x = 5 ; x = 6 ; x = 7 ; x = 8 ; x = 9 ; x = 10 ;
Лямбда-функции.
С версии 5.3 в PHP стали доступны анонимные функции (лямбда-функции, замыкания). Такая функция создается подобно обычной функции, но без имени. результат выражения, описывающего функцию, можно присвоить переменной. После чего использовать её как обычную функцию, или оперировать ею как объектом.
<?php $sum = function($a, $b){ return $a + $b; }; print $sum (100, 200); // out = 300
Как и в классических функциональных языках, лямбда-функции могут замыкать на себя родительский контекст, откуда и название "замыкания".
Замыкание анонимной функции на локальный контекст, в котором она была объявлена, совершается при помощи ключевого слова "use". Переменные, перечисленные в круглых скобках после "use" становятся доступны внутри анонимной функции и после выхода за пределы родительского пространства имен. Например, в случае возвращения анонимной функции как результата работы родительской функции. Ниже - пример возвращаемой анонимной функции, которая при дальнейшем вызове использует для сравнения длину массива, сохраненную в переменной $num.
<?php function foo($arg){ $num = count($arg); return function ($array) use ($num) { $arrayNum = count($array); if ($num === $arrayNum) return "EQUAL\n"; return (($arrayNum > $num) ? "MORE" : "LESS") . "\n"; }; } $data = array(1, 2, 3, 4, 5); $bar = foo($data); print $bar(array(1,2,3)); print $bar(array(1,2,3,4,5,6,7)); print $bar(array(1,2,3,4,50));
Результат:
LESS MORE EQUAL
Стандартные (встроенные) функции PHP.
Несомненно, такой мощный инструмент, как функции, не мог быть обойден разработчиками PHP при разработке возможностей языка. Поэтому PHP содержит огромное количество функций для самых разных задач, начиная определением типа значения переменной и обработкой строк и заканчивая сетевыми запросами и работой с файловой системой. Учитывая количество, нет смысла полностью их описывать, или даже перечислять. Посмотреть и почитать описание можно на php.net .
Функции для работы с функциями.
Для более гибкого оперирования с функциями, PHP предоставляет нам набор специальных встроенных функций. Вот некоторые из них:
call_user_func
<?php
// функция, которая вызывает переданную ей функцию
call_user_func (
function($arg1, $arg2){
print "Print user name: $arg1, $arg2.";
},
'Vasya', 'Pupkin'
);
function_exists
<?php
// определяет определена ли указанная функция
function foo(){
print 'foo fun';
}
function print_exists($name){
if(function_exists($name)){
print "function $name exists \n";
} else {
print "function $name didn't defined \n";
}
}
print_exists('foo');
print_exists('foo2');
Функции с переменным количеством параметров.
Еще одна из функций для функций - func_get_args. Данная функция позволяет получить список переданных в текущую функцию параметров. Это открывает разработчику возможность создавать функции с переменным количеством параметров. Что еще более увеличивает гибкость построения кода, по сравнению даже с предопределенным параметрами.
<?php
//...
function foo(){
$args = func_get_args();
foreach($args as $i => $argument){
print "argument[$i] = $argument \n";
}
}
foo('Vasya', 'manager', 'Pupkina str.', 25);
Результат:argument[0] = Vasya argument[1] = manager argument[2] = Pupkina str. argument[3] = 25
Как мы видим, функции - мощный и удобный инструмент для структурирования и оптимизации кода. Следующий этап на этом пути - классы и объектно-ориентированное программирование.
PS. Бонус для дотошного читателя :)
Возник вопрос о сроке жизни контекста, окружающего лямбда-функцию.
И можно ли привязать несколько функций на один контекст.
При некотором рассмотрении выясняется нюанс, очевидный не сразу.
Во-первых, мы не можем просто так вернуть несколько методов, т.к. возвращается-то один результат.
Во-вторых, в каждый вызов функции, порождающей лямбду, создается новый контекст, переменные которого и становятся доступны анонимной функции.
В итоге получилось вот такое решение, больше похожее на некий странный ООП. Странный в традициях PHP, но вполне имеющий место в JavaScript, например.
Вот это решение.
<?php
function foo(){
$str = "ABC ";
$x = new StdClass();
$x->f1 = function() use (&$str){
static $count = 1;
print ($str .= "Q" . $count++ . " ") . "\n";
};
$x->f2 = function() use (&$str){
static $count = 1;
print ($str .= "T" . $count++ . " ") . "\n";
};
$x->f3 = function () use (&$str){
return $str;
};
return $x;
}
$t = foo();
$f1 = $t->f1;
$f2 = $t->f2;
$f3 = $t->f3;
$f1(); $f2(); $f1(); $f2();
print "\nResult: " . $f3();
Результат:ABC Q1 ABC Q1 T1 ABC Q1 T1 Q2 ABC Q1 T1 Q2 T2 Result: ABC Q1 T1 Q2 T2
PPS. По некотором размышлении пришла мысль, что в ходе чтения статей неподготовленным кодером использование StdClass в последнем примере может оказаться непонятным. Посему пример имеет альтернативную реализацию, см. ниже. Результат выполнения тот же.
Не-объектная реализация мульти-лямбдового контекста.
<?php
function foo(){
$str = "ABC ";
$x = array();
$x['f1'] = function() use (&$str){
static $count = 1;
print ($str .= "Q" . $count++ . " ") . "\n";
};
$x['f2'] = function() use (&$str){
static $count = 1;
print ($str .= "T" . $count++ . " ") . "\n";
};
$x['f3'] = function () use (&$str){
return $str;
};
return $x;
}
$t = foo(); // получаем ссылку на массив
$f1 = $t['f1']; // предаем ссылку на функцию в переменную
$f2 = $t['f2'];
$f3 = $t['f3'];
// вызываем функции с общим контекстом объявления
$t['f1'](); $t['f2'](); // по ссылке в массиве
$f1(); $f2(); // по ссылке в переменных
// вывод итогового результата
print "\nResult: " . $f3();
Ну и немного комментариев, на всякий случай :)
Комментариев нет:
Отправить комментарий