Программирование в PHP 5.3

    Вы наверно слышали о новых особенностях, которые ожидают нас в PHP 5.3, но кто знает где можно их использовать в реальном программировании? Я потратил немного времени чтобы изучить их и решил привести несколько примеров.
     

    Лямбда функции и замыкания.


    Это анонимные функции которые имеют не значительные  отличия. Эти функции более гибкие чем обычные функции и могут быть записаны в переменную или определены там где они нужны.Использование анонимных функций возможно даже в pre-5.3 PHP. Их можно создать при помощи функции  create_function(). Но это громоздко, некрасиво и ненадежно. PHP 5.3 даёт нам возможность делать это в более натуральном и красивом виде.
     

    Лямбда функции

    • Это анонимные функции
    • Могут быть объявлены на лету
    • Могут быть присвоены переменной
    • Могут быть переданы в функцию как параметр
     Примеры использования:
    <?php<br>$lamda = function() { print “Hello World!”; }<br><br>$lamda();<br><br>call_user_func($lamda);<br>call_user_func_array($lamda,array());<br>?><br><br><?php<br>$list = array(22,4,19,78);<br>usort(<br>  $list,<br>  function($a,$b){<br>        if ($a==$b) return 0;<br>        return ($a < $b)?-1:1;<br>    }<br>);<br>print_r($list);<br><br>print_r(array_map(<br>    function ($sn){return ($n * $n * $n);},<br>    array(1,2,3,4,5,6)<br>));<br>?><br><br>* This source code was highlighted with Source Code Highlighter.
     

    Замыкания

    • Это анонимные функции
    • Могут быть объявлены на лету
    • Могут быть присвоены переменной
    • Могут быть переданы в функцию как параметр
    • Могут использовать переменные объявленные  вне функции
     Пример использования:
    <?php
      $string = “Hello World!”;
      $closure = function() use ($string) {print $string; };
      $closure();
    ?>
    <?php
      function getClosure(){
        $string = “Hello World!”;
        return function() use ($string) {print $string; };
    }
    $closure = getClosure();
    $closure();
    ?>


    * This source code was highlighted with Source Code Highlighter.
     

    Различия между использованием use() и globals


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

    Другие случаи использования

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

    И напоследок


    Как вы можете наблюдать, замыкания и лямда функции очень удобны если знать как их использовать. Конечно жаль что придется еще немного подождать перед выходом  PHP 5.3. Но нужно отдать должное разработчикам PHP за столь нужные нововведения.  
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 26

      +1
      Все хорошо, погуглили, пообещали, но живого примера так и не привели :)
        +1
        Было:
        public static function exec($query) {
          global $args;
          if(DEBUG) $start_time = array_sum(explode(" ",microtime()));
          if(func_num_args() > 1) {
            $args = func_get_args();
            $query = preg_replace_callback(
              '/:([0-9]+)/',
              create_function(
                '$matches',
                'global $args; return "\'".sqlite_escape_string(@$args[$matches[1]])."\'";'
              ),
              $query
            );
          }
          self::$result = sqlite_query($query, self::$handle);
          
          if(DEBUG) self::$sql_log[] = array(
            'execution_time' => array_sum(explode(" ",microtime())) - $start_time,
            'query' => $query
          );
          
          return self::$result;
        }

        * This source code was highlighted with Source Code Highlighter.


        Стало:
        public static function exec($query) {
          if(DEBUG) $start_time = array_sum(explode(" ",microtime()));
          if(func_num_args() > 1) {
            $args = func_get_args();
            $query = preg_replace_callback(
              '/:([0-9]+)/',
              function($matches) use ($args) {
                return "'".sqlite_escape_string(@$args[$matches[1]])."'";
              }
              ),
              $query
            );
          }
          self::$result = sqlite_query($query, self::$handle);
          
          if(DEBUG) self::$sql_log[] = array(
            'execution_time' => array_sum(explode(" ",microtime())) - $start_time,
            'query' => $query
          );
          
          return self::$result;
        }


        * This source code was highlighted with Source Code Highlighter.


        По-моему, стало лучше. Мне писать функцию «как есть» удобнее, чем строкой (типа «return \»\";"). Также глобальный массив не захламляется, что вообще замечательно.
          0
          Мне кажется что живые идеи придут в голову сами по себе, и у каждого свои. Я привел парочку примеров для ознакомления с этими прекрасными нововведениями
          +3
          Осталось дописать анонимные и локальные классы и «здравствуй, java!» :-)

          PS Очень рад нововведениям и тому что язык становится более удобным и расширяемым.
            –1
            >«здравствуй, java!» :-)
            скорее groovy ;)
            +1
            Да, то что лямбды, замыкания и пространства имен вводят в версии 5.3, а не 6, как планировалось изначально — не может не радовать, имхо это будет значительным шагом в развитии PHP, каким например было в свое время появление нормального ООП в PHP5, по-сравнению с куцым 4-ым. Обидно только что в обиход она войдет далеко не сразу, и попользовать новшества можно будет только на достаточно больших проектах, использующих, хотя-бы виртуальные, но уже выделенные сервера.
              0
              torag, а почему вы не рассказали про такое важное нововведение, как «пространства имён»? Очень странно, ведь этого новшества так давно ждали, и было бы неплохо рассказать о нем в этом посте.
                +1
                А о пространствах имен уже как-то был топик, возможно из-за этого.
                  0
                  Пространство имен уже не раз здесь обсуждалось. Но могу добавить что нас еще ожидают там Traits и Grafts, которые позволят нам делать множественное наследование. Вот этого уж точно не хватало.
                    0
                    Тогда извините. Этот момент я упустил.
                  +1
                  Пост какой-то некорректный.

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

                  Лямбда-функции в этом контексте это неименованные функции. То есть совсем как обычные функции, но без имени. Их можно присвоить какому-то имени, и тогда получим те функции, с которыми знаком любой программист.

                  Далее, замыкания это такие функции, которые выполняются *в контексте*. Например (тут JS):

                  // обычная функция, контекст ее — все глобальные переменные и другие функции
                  function fun() {
                  … // какой-то код, неважно какой

                  // а вот этой функции доступны все переменные из функции fun
                  // это и будет «контекстом»
                  function bar() {… }
                  // здесь вполне могут быть обращения к переменным, объявленным в fun («захваченным» функцией bar)
                  }

                  Самое интересное в замыканиях, это то, что «захваченные» переменные могут «жить» после того как функция, которая их определила, закончила свое выполнение. Поэтому на замыкания можно смотреть как на объекты (те самые, из ООП) — собственно, это они и есть.

                  Если кого-нибудь интересует более формальное объяснение, то советую почитать о нетипизированном лямбда-исчислении (причем не отвлекаясь на Church encoding и прочую «муть»).
                    0
                    Упс, забыл закрыть } после определения bar. Сорри.
                      0
                      > Далее, замыкания это такие функции, которые выполняются *в контексте*. Например (тут JS):

                      На самом деле (во всяком случае, в JS) можно выделить две теории:

                      — все функции — замыкания (в виду механизма цепи скопов);

                      — замыкание это: функция, которая (а) — имеет «на борту» свободные переменные и (б) — переживает свой лексический контекст;

                        0
                          0
                          > замыкание это: функция, которая (а) — имеет «на борту» свободные переменные и (б) — переживает свой лексический контекст;

                          Это и есть верный ответ.

                          > все функции — замыкания (в виду механизма цепи скопов);

                          Авторы ECMAscript просто сильно напутали с областью видимости. :)
                            0
                            > Это и есть верный ответ.

                            Вернее, это наиболее полное использование этой конструкции (замыкание) в JS.

                            > Авторы ECMAscript просто сильно напутали с областью видимости. :)

                            Ничего они не напутали, механизм цепи скопов работает одинаково — для вложенных и глобальных функций. Так что, эта теория (все функции — замыкания; в JS) тоже имеет право на существование, правда, здесь интерес только теоретический.
                        0
                        Замыкания

                        * Это анонимные функции

                        Вот, жаль, что замыкание здесь описывается как обязательно анонимная функция. Вообще, в теории, анонимная функция — лишь частный случай замыкания; замыкание может быть и именованной функцией (но не в PHP).

                        Так же, можно отметить, что use создает локальную копию переменной из скопа выше (в отличии, например, от Javascript). Чтобы переменная ссылалась, нужно явно передавать её в use по ссылке (либо использовать модификатор global).
                          +1
                          Наконецто php обзавёлся фитчами функционального программирования! Очень нехватало
                            0
                            Вопрос: в замыканиях будет использоваться лексический или динамический скоп?
                              0
                              Лексический конечно
                                0
                                Почему это, «конечно»?
                                  0
                                  PHP позиционируется как простой язык с защитой от дурака, а динамическая область видимости может подкладывать неприятные «сюрпризы». Некоторые вообще считают её злом наравне с goto.
                                    0
                                    Получается, что PHP — язык с защитой от дурака, созданный дураками для дураков.

                                    P.S. Простите, не удержался ;-)
                            • UFO just landed and posted this here
                                0
                                Омг. Лямбды приделали. А array_reduce в качестве initial теперь что-то кроме целых цислел принимает? (см. antilamer.livejournal.com/269560.html ).
                                • UFO just landed and posted this here

                                  Only users with full accounts can post comments. Log in, please.