Как стать автором
Обновить

Комментарии 69

Ого, в mail.ru пресс-секретарь разбирается в замыканиях php.
Круто.

замыкания (closures).

О последних я и хочу рассказать.

Зачем нужны замыкания в PHP я понимаю слабо.


Не хватает строчки
Статью разместила по просьбе JohnDoe, но у него нет кармы чтобы разместить в соответствующем блоге.


Всех с пятницей.
Это к тому, что мог бы запостить автор этой статьи, как делается в блоге компании Abbyy, чтобы он мог отвечать на заданные комментарии/вопросы/размышления
Челябинские пресс-секретари настолько суровы, что на завтрак читают MSDN, а в перерывах на рекламу изучают замыкания и пишут статьи.
возможно, девелопера _заставили_ написать эту статью. возможно, стимулировали термо-ректально. надо срочно обратиться в комитет по защите прав человека!
Я все еще не могу поверить что вижу это:
а) в блоге Мэйл.ру
б) от Комисаровой

Ну да ладно, все равно молодцы, что пишете не только пресс-релизы :-)
Валерия, похоже люди чего-то не знают :)
Непонятно, зачем делается такой упор на анонимность функций. Какая разница, анонимная функция или нет. Возможность объявлять анонимные функции — это просто синтаксический сахар.

Замыкания к анонимности функций никакого отношения не имеют. Писать, что замыкание — это комбинация 2 факторов, 1 из которых — анонимная функция — неправильно.
> Возможность объявлять анонимные функции — это просто синтаксический сахар.
вообще исторически и логически скорее на оборот, а в php… ну что тут поделаешь :D
Сахарный синтаксис?
Снимаю свои претензии к автору топика. Что-то там с терминологией капец какой-то даже в официальном мануале .
Anonymous functions, also known as closures

Ну и каша. Такое ощущение, как будто они сами не очень понимают, что сделали. Очень странно и удивительно.
Причём имеют в виду скорее всего просто возможность присваивания функции переменной :)
Эта возможность + сохранение родительского scope — это уже хотя бы замыкание.
Че ж тут удивительного? PHP весь – каша. Официальный мануал зачастую вообще содержит документацию багов отдельных версий, так как у языка нет нормальной четкой спецификации.

У меня такое ощущение что они сначала что-то кодят а потом кое-как документируют что получилось.
Реализация замыканий в PHP не бесспорна. Порой мне кажется что они специально выбирают самые «хитрые» пути.
Неверно. Возможность обьявления анонимных функций — удобна для авторов библиотек. Гарантирована непересекаемость по именам.
Ух, что я вижу! Неужели в mail.ru что-то пишут на PHP? Я почему-то полагал, что у вас там все на перле и/или с++.
Для многих применений PHP эффективнее, чем вышеуказанное.
Либо по скорости разработки, либо по производительности, либо по простоте поддержки, либо по цене.
они пали едва ли не последними из крупных российских компаний и таки дали объявление о наборе php разработчиков
НЛО прилетело и опубликовало эту надпись здесь
Вот вот и я подумал, а разве замыкания не нужны для анонимных функции это не одно и тоже?

Автор учи мат часть: Closure (computer science)!
В Си вообще нет замыканий, о боже, как он отстал! Абзац со сравнением lisp'а и php достаточно смешной и нелогичный.

Ну а так — да. PHP был типичным императивным языком для быстрых скриптов, и только сейчас вырывается на какой-то уровень технологий.
А, и __invoke как раз таки офигенное нововведение, лучше чем просто переменные-функции. Вопросы производительности стоит оставить оптимизаторам. А внутренние процессы в том же JS такие же.
вырывается? по-моему тут он просто пытается догнать.
Пытается догнать что? У каждого свое русло, у PHP тоже, и для своего русла он не плох. Разработчики прсто делают нововведения, ускоряют работу языка. Что в этом плохого?
Они тоже люди я проверял :)
лямбда функция это
1) анонимная функция которая может быть сохранена в переменной
2) в отличие от функции созданной create_function уничтожается при выходе из области видимости и не жрет память бесконечно.

замыкание в дополнение к этому могут иметь доступ к переменным родительской области видимости.

Именно это я и имел в виду говоря «замыкание» (использует переменные родителей) и «анонимная функция» (не использует)! Я понимаю что технически в некоторых языках это одно и то же.
Правильно, зачем делать нормальную реализацию замыканий, ведь для этого придется перелопатить весь говнокод из интерпретатора PHP (слова разработчика, который был в dev team)! Намного лучше сделать идиотский magic method (*объект* используется как функция — WTF?!?!) и добавить синтаксического сахара для создания нужного объекта с таким методом.

Интересно, доступ к родительской области видимости делается при помощи банальных ссылок на нужные переменные, чтобы сборка мусора их не прибила?

А теперь смотрим как это все реализовано в том же Javascript и перестаем удивляется словам про кривую проектировку PHP.
НЛО прилетело и опубликовало эту надпись здесь
>чтобы сборка мусора их не прибила?
1) как может сборка мусора прибить РОДИТЕЛЬСКИЕ переменные?
2) какая сборка мусора в PHP? там тупо счетчик ссылок.
Открываем википедию и узнаем, что сборка мусора в простейшем случае делается именно при помощи подсчета ссылок. Для сборки мусора не важно какая область видимости. Вообще.
Один только phpdaemon практически весь построен на замыканиях, так как это практически единственая метода для реализации асинхронности без гемороя.
В корпоративном блоге. Неожиданно.
Автор статьи, я. Готов отдуваться.

P.S. В продакшене у нас (на hitech.mail.ru) PHP действительно не используется. Зато используется JQuery. Просто PHP интересен в плане синтаксиса и реализации замыканий, да и вообще релиз 5.3 очень интересный.
Вообще как я писал выше замыкания нужны для создания анонимных функции, странно что вы этого не знаете. Вся статья не о замыканиях, а о анонимных функциях!
Мы говорим об одном и том же, разница в терминологии.
Я удивлен, что статья попала на главную…

Причин две:
1) Статья совершенно не про «Замыкания в PHP»… Об этом хотябы говорит ваша фраза «Зачем нужны замыкания в PHP я понимаю слабо».
2) По поводу замыканий JS — полно статей на Хабре. Я негодую — что нового в этой статье?

Аннонимные функции у меня во FW используются так:
getElementObject('Form')
  ->onValidate(function($fields){
   //проверки
  })
  ->onSubmit(function($fields){
   //что делаем, если порядок
  })
  ->onError(function($fields){
   //что делаем, если всё плохо
  });


* This source code was highlighted with Source Code Highlighter.


Замыкания так:
$login = Auth::getLogin();

getElementObject('Form')
  ->onValidate(function($fields) use ($login){
    $newLogin = $fields->getElementObject('.name')->getValue();
    //Проверяем, что пользователь ввел не сам себя
    return $login != $newLogin;
  });


* This source code was highlighted with Source Code Highlighter.

Смысл этого в том, чтобы определять $login не внутри Validate функции.
Код во втором примере можно назвать практичным, но трудно назвать элегантным. Синтаксис PHP для замыканий тоже не добавляет изящества.
В вашем случае, элегантность кода = создание дополнительного Validate класса в который идет загрузка $login, затем установка полю проверки?

class LoginValidate extends Validate{
  function setLogin($login){
   $this->login = $login;
  }

  function onValidate($value){
    return $this->login != $value;
  }
}

///...

$login = Auth::getLogin();

getElementObject('Field.name')
  ->onValidate(
     classBuilder::createClass('LoginValidate')
       ->setLogin($login)
  );

* This source code was highlighted with Source Code Highlighter.


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

Но вариант с классами — это засирание кодом и усложнение структуры. Очевидно, что людям разобраться и найти нужное будет намного сложнее. Создавать новый класс для каждой проверки? Создать один класс, который будет делать все проверки, который нужно искать по названию?

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

Второй пример необходим только в случае частого использования.
1. Зачем вы обрушили на нас этот баян? Я об писал больше года назад (18 мая 2009 года).
2. То что вы слабо представляете зачем нужны closures в PHP это говорит лишь о том что вы не в теме таких вещей как phpDaemon :-) Да и многих других интересных вещей.
Лучше вместо понтов и рассказали, зачем же всё-таки замыкания нужны и что за вещи такие phpDaemon. А то как детсаде ей богу «нет, я первый в песочницу залез, нет, это моё ведерко!»
P.S. Замыкания в PHP нужны потому что нам надоело видеть create_function под ободками наших унитазов.
Мне кажется, замыкания вообще не очень красиво смотрятся в ООП. Но это на мой вкус.
Вам и goto подозрительным кажется!
Почему вы говорите так, как будто в этом есть что-то плохое?
а что вы имеете против goto, мне лично кажется странно что его ввели так поздно!
1. основное отличие от create_function или eval в возможности нормальной отладки.

2. в руби (который также ориентирован на веб-скрипты) активно используются замыкания.
Тогда простите меня, это ппц — за год не разобраться, для чего они нужны…
За год я убедился, что лично мне в PHP они не нужны. Очевидно же, что мое суждение субъективно. Ваше, кстати, тоже. Мы же с вами выше убедились, что все то же самое можно сделать и без замыканий. При этом я не отказываю вашему коду в практичности. И считаю здорово, что вы нашли им применение. Только не понимаю почему вы так их отстаиваете?
Тимур, огромное спасибо, вы первый кто мне смог полноценно и доходчиво объяснить, что такое замыкания и лямбда функции (почему они так называются) и для чего нужны :)
И для чего в PHP нужны замыкания? :)
Какая разница в PHP или не в PHP, просто теперь понятно, что это такое :)

Спасибо! Я старался написать просто и с примерами. За это в основном и получил упреки в том, что в статье нет ничего сверхъестественного. Приятно, что вам она оказалась не бесполезной!
А я-то обрадовался…
Причем копипаст практически дословный, включая примеры и речевые обороты!
Автору:

Все эти прелести действительно очень полезны. Например, используем шаблоны на чистом PHP, layout.php:

<div id=«header»><%= yield_content('header') %>

и где-нибудь

<% for_region('header', function() { %>
тра-та-та
<% }); %>

Понятно, идея взята из Rails.
Вернемся к PHP. В нем все не так красиво как в Javascript. Во-первых, для того чтобы функция могла использовать переменные родительской функции, надо это явно указать в ее определении (это следует из идеологии языка)

Мне это наоборот представляется крайне разумным ходом, поскольку в таком случае все ненужные для замыкания локальные переменные будут удалены после завершения вызова функции, освободив память.
Не будут, память освобождается не сразу.
Согласен, не совсем корректно выразился. Но поскольку в PHP с некоторых пор есть сборщик мусора, то в какой-то момент она таки освободится — за исключением переменных, использованных в замыкании, что весьма логично на мой взгляд. Это я и хотел сказать.
Пример, где замыкания реально нужны:
www.pgregg.com/projects/php/preg_find/preg_find.phps
искать строку: $filesort =
Автор конечно гм… со своеобразным кодстайлом, но файлик понятный без доп знаний.
Мне есть что вам ответить. Похоже это библиотека и стиль там процедурный. Соответственно create_function используется прежде всего, чтобы не засирать глобальное пространство имен (но, кстати, все равно это делает).

А если бы они применили ООП подход?

Во первых они бы избавились от некрасивых
define('PREG_FIND_RECURSIVE', 1);
define('PREG_FIND_DIRMATCH', 2);

засунув все константы в класс.

Во вторых они бы сделали сортировку, передав в uasort метод класса и из метода имея доступ ко всем свойствам, в том числе параметрам сортировки.

Разве это не сделало бы код прозрачнее и юзабельнее?
Осталось дождаться пока array_map() и подобные функцию научатся работать в несколько потоков.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий