Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Урок №21 - Замыкания в PHP

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 » 

> Описание: Лямбда-функции и их особенности.
EuGen Администратор
Отправлено: 11 Марта, 2012 - 15:35:18
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Приветствую,
Этот небольшой урок создан, чтобы осветить тему замыканий в PHP. Прежде всего, стоит пояснить, что такое замыкание. Одно из определений замыкания:

Замыкание - это анонимная функция, то есть функция, не имеющая имени.

В какой-то мере это отражает суть замыкания. Важно понимать, что замыкание есть некая самостоятельная сущность с теоретической точки зрения и не путать само понятие замыкания с тем, как оно конкретно реализовано. Ниже я опишу в чем разница.

О применимости
Для того, чтобы лучше понимать область применимости замыканий, следует вспомнить (или узнать, если вы еще этого не сделали), что в PHP существует так называемый псевдотип данных - callback. По сути, переменные такого типа являются правильными с точки зрения интерпретатора сущностями для вызова. Иными словами, данные такого типа могут быть использованы как функции. Строго говоря, этот тип шире, чем просто замыкания, в него могут входить также и строковые названия функций. Приведу полный список:

0. Собственно, замыкания
1. Строки, являющиеся именами пользовательских либо стандартных функций (например, "trim")
2. Имена методов, в том числе статичных

При этом стоит помнить, что в последнем случае фактически callback-данные будут представлять собой массив с указанием объекта в элементе с нулевым индексом и имя метода - в элементе с первым индексом. Например:
PHP:
скопировать код в буфер обмена
  1. //Правильная callback-переменная типа 0:
  2. $fnCallback=function ($sItem)
  3. {
  4.    return trim($sItem);
  5. };
  6. //Правильная callback-переменная типа 1:
  7. $fnCallback="trim";
  8. //Правильная callback-переменная типа 2 (указывающая, что данные будут обработаны как Foo->bar)
  9. $fnCallback=array("Foo", "bar");


- выше я первый раз указываю синтаксис замыканий, что, вероятно, преждевременно, но если вам не понятно - пока пропустите и вернитесь к примеру позднее. Данные callback-типа могут использоваться в функциях, например, array_walk или call_user_func.

Немного формальности
Теперь пора рассказать собственно о том, как строятся замыкания. В зависимости от версии PHP они могут:

0. Не поддерживаться вовсе, версия PHP < 4.0.1
1. Поддерживаться только через create_function, версия PHP 4 >=4.0.1 или PHP 5 < 5.3
2. Поддерживаться и через create_function и через специальный синтаксис.

Вариант, когда замыкания не поддерживаются вовсе, нас не интересует, и потому я расскажу о двух способах создания замыканий (тех, что в пунктах 1. и 2.).
Итак, создание замыканий при помощи create_function:
Разумеется, наиболее полное описание этой функции есть на официальном сайте, но я сделаю некоторое резюме.
Функция принимает два параметра и оба - строковые. Строка-список аргументов, разделенных запятой, указывается первым параметром, PHP-код указывается вторым параметром.
Приведу пример:


- по сути, создает функцию, принимающую два параметра и возвращающую их сумму. А как же выглядит собственно $fnCallback? Здесь все просто - create_function вернет строку для созданного замыкания. По сути, это будет некоторым уникальным идентификатором замыкания в глобальном пространстве имен. Модифицируем предыдущий пример и увидим:
PHP:
скопировать код в буфер обмена
  1. $fnCallback=create_function('$a,$b', 'return $a+$b;');
  2. var_dump($fnCallback);

- на выходе

В дальнейшем созданное только что замыкание можно использовать в функциях, ожидающих callback-параметры. Используем только что созданное замыкание:
PHP:
скопировать код в буфер обмена
  1. $rgOdd  = array(1,3,5,7);
  2. $rgEven = array(2,4,6,8);
  3. $rgResult=array_map($fnCallback, $rgOdd, $rgEven);
  4. var_dump($rgResult);

- даст массив, содержащий суммы элементов в одинаковых индексах:
PHP:
скопировать код в буфер обмена
  1. array(4) {
  2.   [0]=>
  3.   int(3)
  4.   [1]=>
  5.   int(7)
  6.   [2]=>
  7.   int(11)
  8.   [3]=>
  9.   int(15)
  10. }

Расскажу об одном подводном камне, который существует для create_function. Так как оба её аргумента - строки, то использование двойных кавычек приведет к тому, что интерпретатор будет подставлять значения переменных (вместо того, чтобы расценивать написанное как PHP-код). Почти всегда это - не то, что нужно, и, чтобы избежать подобного поведения, нужно либо экранировать знаки "$", либо использовать одиночные кавычки.

Второй способ создания замыканий - с ключевым словом function
Доступно только начиная с PHP 5.3. В этом случае замыкание создается схоже с объявлением функции. Есть два существенных отличия - во-первых, такая функция не имеет имени, во-вторых, она может обращаться к своему контексту при помощи ключевого слова use. Это схоже с использованием ключевого слова global, но не идентично ему. Приведу синтаксис:
PHP:
скопировать код в буфер обмена
  1. $fnCallback=function($a, $b) use ($c)
  2. {
  3.    return $c*($a+$b);
  4. };

Как видно, функция по-прежнему принимает два параметра, а так же опирается на некоторую переменную контекста $c. Переменная контекста - означает, что её значение будет таким, каким оно является на момент создания замыкания. Чтобы было понятнее, приведу два примера:
первый:
PHP:
скопировать код в буфер обмена
  1. $fnCallback=function($a, $b) use ($c)
  2. {
  3.    return $c*($a+$b);
  4. };
  5. $c=2;
  6. $rgOdd  = array(1,3,5,7);
  7. $rgEven = array(2,4,6,8);
  8. $rgResult=array_map($fnCallback, $rgOdd, $rgEven);
  9.  
  10. var_dump($rgResult);

и второй:
PHP:
скопировать код в буфер обмена
  1. $fnCallback=function($a, $b)
  2. {
  3.    global $c;
  4.    return $c*($a+$b);
  5. };
  6. $c=2;
  7. $rgOdd  = array(1,3,5,7);
  8. $rgEven = array(2,4,6,8);
  9. $rgResult=array_map($fnCallback, $rgOdd, $rgEven);
  10.  
  11. var_dump($rgResult);
  12.  

- как видите, в во втором варианте я заменил use на global. Так как в первом случае переменная $c не была объявлена на момент создания замыкания, то ее попросту нет в контексте и потому первый пример выдаст что-то подобное:
PHP:
скопировать код в буфер обмена
  1. Notice:  Undefined variable: c in ... on line ...
  2. array(4) {
  3.   [0]=>
  4.   int(0)
  5.   [1]=>
  6.   int(0)
  7.   [2]=>
  8.   int(0)
  9.   [3]=>
  10.   int(0)
  11. }

В то же время второй пример использует $c из глобального пространства имен, что даст результат:
PHP:
скопировать код в буфер обмена
  1. array(4) {
  2.   [0]=>
  3.   int(6)
  4.   [1]=>
  5.   int(14)
  6.   [2]=>
  7.   int(22)
  8.   [3]=>
  9.   int(30)
  10. }

Однако стоит помнить, что, как правило, замыкания имеют смысл в контексте с какими-либо данными, использование же global сильно ухудшает читаемость кода (предлагаю подумать, почему).
Что же будет, если одновременно указать и global и use? Очевидно, что мы используем ключевое слово global внутри тела замыкания и потому оно перекроет передаваемый через use контекст.

Что можно делать в замыканиях
- Как и в обычных функциях, в замыканиях возможно принимать ссылки при помощи знака &. Более того, замыкание может модифицировать свои параметры, если те переданы по ссылке (ровно так же, как и обычная функция).
- Если PHP версии 5.3 и выше, то замыкания, созданные при помощи ключевого слова function, будут не строками, а экземплярами (объектами) специального класса Closure. По сути, этот класс сделан для совместимости и, например, невозможно создать его экземпляр иначе как создавая замыкание (т.к. его конструктор запрещает делать это). Таким образом, это - еще одно отличие от create_function. А возможность, которая достигается за счет того, что замыкание есть объект класса - начиная с PHP 5.4, этот класс получил методы, позволяющие контролировать анонимные функции после их создания. Это - выжимка документации.
- Замыкания можно сделать рекурсивными. Для этого достаточно применить нехитрый прием - в качестве параметра принимать callback-данные, на которые опираться внутри замыкания. Например, функция array_walk_recursive может быть заменена следующим кодом:
PHP:
скопировать код в буфер обмена
  1. $fnWalk = function($rgInput, $fnCallback) use (&$fnWalk)
  2. {
  3.     foreach ($rgInput as $mKey => $mValue)
  4.     {
  5.         if (is_array($mValue))
  6.         {
  7.             $fnWalk($mValue, $fnCallback);
  8.         }
  9.         else
  10.         {
  11.             $fnCallback($mValue, $mKey);
  12.         }
  13.     }
  14. };

Обратите внимание на переменную контекста.
- Если PHP версии 5.4, то существует возможность использовать $this внутри тела замыкания. Это подобно обращению к свойствам внутри класса.
- Если PHP версии 5.4, то допустимо определять "альясы" для параметров замыканий, по которым они будут доступны внутри самого замыкания. Это выглядит так:
PHP:
скопировать код в буфер обмена
  1. $fnCallback=function($x) use ($y as $fMultipier)
  2. {
  3.    return $x*$this->fMultiplier;
  4. }

Пример дает представление так же и об использовании $this

- В качестве недостатка замыканий приведу то, что данные этого типа невозможно сериализовать стандартной функцией serialize, что делает неудобным их присутствие в качестве свойств объектов.

Немного рекомендаций
Так зачем же использовать лямбда-функции? Это - воможность языка, эта конструкция в большинстве случаев может быть заменена другими приемами.
Прежде всего - замыкания полезны при обработке массивов. Очень часто бывает необходимо что-либо сделать для всех элементов массива. В этом случае замыкания - лаконичный и наглядный способ это сделать. Однако если происходит обработка массива, которая не предполагает обработку всех его элементов, то, как правило, от использования замыканий стоит воздержаться. Например, задача - обнаружить, есть ли в массиве значение, которое содержит только символы латиницы a-z.
При помощи цикла:
PHP:
скопировать код в буфер обмена
  1. $rgData=array('foo12a', 'test', 'bar13b', 'baz14c');
  2.  
  3. $bFound=false;
  4. foreach($rgData as $sData)
  5. {
  6.    $bFound = $bFound || preg_match('/^[a-z]+$/', $sData);
  7.    if($bFound)
  8.    {
  9.       break;
  10.    }  
  11. }

И при помощи замыкания:
PHP:
скопировать код в буфер обмена
  1. $rgData=array('foo12a', 'test', 'bar13b', 'baz14c');
  2.  
  3. $bFound=false;
  4. array_walk($rgData, function($sValue) use (&$bFound)
  5. {
  6.    $bFound = $bFound || preg_match('/^[a-z]+$/', $sValue);
  7. });

- как видим, второй вариант несколько "красивее". Однако же - в первом случае цикл прекратит свое выполнение уже на втором элементе, тогда как во втором случае будет пройден весь массив. В случае, если элементов 4 особой разницы во времени нет, но если счет идет на десятки тысяч, ситуация может измениться.
Поэтому моя общая рекомендация - как и все остальное, замыкания хороши при их использовании в меру. Не стоит гнаться за красотой кода, если при этом явно пострадает производительность.

В качестве заключения, как обычно, приведу вопросы к уроку:
0. Напишите замыкание, которое меняет местами ключи и значения массива
1. Можно ли использовать замыкания в качестве параметров замыканий? Если да/нет то почему?
2. Что произойдет, если переменную контекста замыкания использовать также в качестве ее параметра?


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Bio man
Отправлено: 11 Апреля, 2012 - 23:00:48
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2751
Дата рег-ции: Июль 2010  
Откуда: Даугавпилс, Латвия


Помог: 52 раз(а)




0.
PHP:
скопировать код в буфер обмена
  1. $fnFunction = function($rgData){
  2.         return array_flip($rgData);
  3. }

1. Да. В РНР5 >= 5.3 замыкание является экземпляром класса Closure, так что нет противоречий передачи объекта в качестве аргумента.
2. Не понятен мне вопрос... Как можно переменную контекста ф-ции передать в эту же ф-цию? Ну можно вызвать себя же рекурсивно, например,
PHP:
скопировать код в буфер обмена
  1. $fnClosure = function() use ($fnClosure){return $fnClosure();}

(Отредактировано автором: 11 Апреля, 2012 - 23:02:20)

 
 Top
LIME
Отправлено: 10 Ноября, 2012 - 21:20:50
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




Спойлер (Отобразить)
а тут несколько иное определение
http://learn[dot]javascript[dot]ru/closures
и врядли дело в языке
 
 Top
EuGen Администратор
Отправлено: 10 Ноября, 2012 - 22:12:39
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




В материале выше я вообще не даю строгого определения термина "замыкание", приводя лишь описание:
EuGen пишет:
В какой-то мере это отражает суть замыкания. Важно понимать, что замыкание есть некая самостоятельная сущность с теоретической точки зрения и не путать само понятие замыкания с тем, как оно конкретно реализовано. Ниже я опишу в чем разница.

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


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
LIME
Отправлено: 10 Ноября, 2012 - 22:24:54
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




мне показалось что и смысл отличается
я не о приведенном отрывке а о статье по ссылке вообще
 
 Top
EuGen Администратор
Отправлено: 10 Ноября, 2012 - 23:14:20
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Разумеется, отличается. Равно как и сужение определения по сравнению с тем, что приведено, например, по ссылке, что я дал в комментарии выше. О причинах я уже говорил. Это не другое определение - просто более специализированное (опять же, как и то, о чем говорится в статье, на которую Вы ссылаетесь).


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
LIME
Отправлено: 10 Июня, 2015 - 22:33:55
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




Цитата:

Немного путаницы. Авторы версии 5.3, в которой впервые появился современный синтаксис анонимных функций, перепутали два понятия — собственно анонимная функция (лямбда-функция) и замыкание (замыкание переменной на контекст этой анонимной функции). Именно поэтому анонимные функции реализованы в языке с помощью системного класса Closure, а не, к примеру, Lambda, как стоило бы ожидать. Имейте этот факт в виду на собеседовании — многие интервьюеры сами путают понятия «лямбда-функция» и «замыкание».
вот примерно это я имел ввидуУлыбка замыкание это функция связаная с контекстом создающей функции
 
 Top
MiksIr
Отправлено: 11 Июня, 2015 - 01:21:58
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Ничего они не путали. Более того, в PHP сначала появился патч на лябда функцию, но его решили не принимать, ибо без замыкания в нем толку мало. И где-то через пол года патч был переделан на поддержку замыкания.


На самом деле говорить, что "замыкание это функция связаная с контекстом создающей функции" не совсем верно. Ибо эта фраза как бы намекает, что теперь между этим контектом и контекстом лябды прямая и непорочная связь. Но это не всегда так. У лябды может быть как бы свой контекст, но со скопированными туда переменными.

Замыкания в PHP, конечно, особенные, требующие указания замыкаемых переменных, но от этого замыканием быть не перестает.

Другое дело, конечно, что лямбду без use замыканием уже назвать сложно. Но постоянно называть в разговоре по-разному как-то глупо. Вот и называют замыканием.


-----
self-banned
 
 Top
LIME
Отправлено: 11 Июня, 2015 - 01:41:48
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




MiksIr пишет:
Вот и называют замыканием.
вот именно
Название не несет в себе концептуального смысла
Замыкание можно реализовать и через методы класса
И оно будет замыканием
Но лямбду саму по себе назвать замыканием есть путаница в терминологии
MiksIr пишет:
что теперь между этим контектом и контекстом лябды прямая и непорочная связь
не понял
Видимо снова дело в том что замыкание прочно ассоциируется с лямбдой
Но вобщем да
Смысл замыкания именно в прямой связи с контекстом создающего скопа
Иначе в нем нет и смысла
(Добавление)
Или имелось ввиду что это не связь с создающим скопом в любой момент времени, а только в момент создания замыкания?
Да, тут я допустил неточность
Используемые значения из создающего скопа зафиксированы в замыкании что можно изменить передавая в замыкание ссылку а не значение
Но сути не меняет
(Добавление)
EuGen пишет:
Замыкание - это анонимная функция, то есть функция, не имеющая имени.
ну...я вас умоляюУлыбка
 
 Top
MiksIr
Отправлено: 11 Июня, 2015 - 02:08:48
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Цитата:
Или имелось ввиду

Да, почти это. Ссылка или не ссылка, можно вообще ее передать или нет - это не есть предмет определения замыкания, это уже вопрос конкретной реализации в языке программирования (если в отрыве от PHP говорить).

В случае PHP без use можно сказать, что мы замкнули 0 переменных, но меанизм замыкания есть ;) Тем более, например, и без всякого use внутри объекта замыкается $this.

Я думаю просто следует разделять замыкание как процесс и замыкание как название синтаксической конструкции языка, позволяющее замыкать ;) В этом случае - в php замыкания и "не учите меня жить" =)


-----
self-banned
 
 Top
LIME
Отправлено: 11 Июня, 2015 - 02:16:25
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




Ыгым
Мы замкнули 0 переменных но замыкание есть
Похоже на отговорку
Замыкание было выделено в отдельный термин именно как определенный механизм
Если этот механизм не используется то как можно к конструкции применять термин?
Тем более заменять его значение(лямбда это лямбда)
(Добавление)
MiksIr пишет:
и "не учите меня жить" =)
ой всеУлыбка
(Добавление)
Может я просто ошибаюсь в определении замыкания? В общем контексте не применяя к пхп что есть замыкание?
(Добавление)
А пока для меня называть лямбду замыканием это примерно как сохранить конект к бд в статический член класса и назвать это особенной реализацией синглтона в пхп
Сравнение глупое но мысль мою уточняет
 
 Top
MiksIr
Отправлено: 11 Июня, 2015 - 02:44:05
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Цитата:
Замыкание было выделено в отдельный термин именно как определенный механизм

В том то и дело, что механизм есть.

Например, берем язык, который анализирует тело лямбды, смотрит - какие нелокальные переменные там используются и копирует их. Только их, ибо нафига в лямбду передавать все переменные если они не используются?

В таком случае если лямбда не использует ни одной "внешней" переменной - ни одна переменная не будет замкнута. Остается ли эта лямбда замыканием? =)

Вот я от этого отталкиваюсь. Механизм замыкания есть, хоть им и не воспользовались. Значит вроде как замыкание.

Цитата:
Может я просто ошибаюсь в определении замыкания? В общем контексте не применяя к пхп что есть замыкание?

Это ваще очень сложно и определений много и все они вроде об одном, но в то же время - различаются ;)
Я определяю замыкание - как механизм создания функции с не пустым лексическим окружением.
Но в общем в английской вики более-менее написано. Немного заумно, но с такими терминами иначе низя.

(Отредактировано автором: 11 Июня, 2015 - 02:44:38)



-----
self-banned
 
 Top
LIME
Отправлено: 11 Июня, 2015 - 02:48:04
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




MiksIr пишет:
Остается ли эта лямбда замыканием? =)
нет
Перестает быть замыканием
MiksIr пишет:
функция создаваемая с не пустым лексическим окружением.
и я об этом
MiksIr пишет:
Но в общем в английской вики более-менее написано. Немного заумно, но с такими терминами иначе низя.
да
Надо будет изучить
Возможно я изменю свое мнение но... блин это же так напряжноУлыбка я думал тут мне хоть в основных тезисах опишутУлыбка
(Добавление)
Вот смотри
Термин придуман для особенности использования механизма и какая нафиг разница что внутрях ???
Если нет связи с окружением значит нельзя использовать особености механизма
Значит термин теряет свое назначение
Хотя я думаю ты давно меня понял как и я тебя...мне кажется
Я за то чтобы не вносить путаницу, вне зависимости от нутра реализации вконкретном языке
 
 Top
MiksIr
Отправлено: 11 Июня, 2015 - 03:06:21
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Да я понял. Ты говоришь о наличии или отсуствии замкнутых переменных в каждом конкретном случае. А я говорю о наличии в языке синтаксической конструкции позволяющей (!) замкнуть переменные.

Потенциально с твоим вариантом больше путаницы, ибо на вопрос "а есть ли в этом языке программирования замыкания" становится сложно ответить. Боюсь, что ответ "в какой-то программе есть, а в какой-то нет" скорее всего вгонит в ступор =)

Но в общем изучить надо. Причем не только статью про замыкания, но и про лямбду и first-class function. Хотя брать только вики тоже не правильно ;)


-----
self-banned
 
 Top
LIME
Отправлено: 11 Июня, 2015 - 03:12:37
Post Id


Активный участник


Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010  


Помог: 322 раз(а)




А мне кажется что гораздо понятнее будет сказать что например данные берутся из замыкания
Это более приближенный к практике пример чем речь о поддержке замыканий в языке
тем более замыкания можно эмулировать
Это как писать процедурный код на классах и/или ооп в языке без классов
(Добавление)
MiksIr пишет:
а есть ли в этом языке программирования замыкания
некорректно
есть ли в языке нативная поддержка замыканий?
(Добавление)
Не убедил еще?))
(Добавление)
Хотя неважно
KISS baby
А замыкания только добавляют сложность
(Добавление)
Я о том понимании замыканий которое отстаиваю
(Добавление)
Вот такой вот урок для новичков)))
Без научной степени в ракетных науках не разберемся)))
(Добавление)
И итоговая мысль
мне кажется что замыкания это то что было придумано потому что это можно было придумать
просто интересная схема и не более
лучше обходить стороной

(Отредактировано автором: 11 Июня, 2015 - 03:51:27)

 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Уроки php »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB