Pull to refresh

Comments 58

Что такое «лямбда-функции и замыкания» любой узнает открыв мануал. А ваши примеры настолько нереальны, что кроме как «WTF?!?!» мыслей в голову не приходит. Но даже это не главное. Главное то, что бел пол-литра в ваших примерах не разобраться.
Если бы все могли открыть мануал и во всем разобраться, то никому не нужно было вести блоги, писать статьи с примерами. Ну а примеры возможно да, с следующий раз я обязательно это учту
Ну как-бы в том и суть вопроса, что мануалы по php настолько интуитивно-понятны — что любой их может открыть и разобраться, и исключительно нежелание это делать порождает и огромное количество говнокода на php, что таки присутствует, и высокомерное отношение других программистов к программистам на php.
Я вот лично например наблюдал как человек ругал php за то что он не может вызвать функцию с произвольным количеством параметров, и потому приходится делать так:
function call_user_func_array($function, array $params) {
  switch(count($params)) {
  case 1:
    return $function($params[0]);
  case 2:
    return $function($params[0], $params[1]);
  // ...
  }
}
Вместо того чтобы таки открыть мануал и найти там call_user_func с call_user_func_array рядом. И таких примеров много… прямо скажем «тысячи их».
Почему нереальны? Вполне хорошие примеры. Последний так вообще понравился.
Мне тоже примеры не понравились: во-первых, это все через pdo давно делать надо, во-вторых действительно не наглядно.
Кстати, а мне кажется что PDO не самое удобное. Там, на мой взгляд, неудобно организованы placeholder'ы и работа с результатами выборки
На вкус и цвет, в любом случае вокруг PDO легко написать собственную обертку со своими преферансом placeholder'ами и поэтессами обработкой результатов выборки.
Вы думаете новички поймут вот это $regExp = '/([^{"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])*"|{[^}{]+})/'?
Я, например, с первого взгляда тоже понять не могу что делает эта регулярка, но для того, чтобы понять механизм работы с ними — это абсолютно не важно
«с ними» — я имел ввиду тему топика.
При написании топика не думал что это может оказаться столь важным, хотел описать механизм работы с лямбдами и привести более-менее прикладной пример и не ограничиваться примерами с умножением чисел на множитель или вроде того
ох уж это размножение зубочисток…
Приведите, пожалуйста, примеры которые показывают что да, лямбда-функция классная вещь и как это делать без лямбда-функции.
А то, напоминает как пытаются человеку, который все время пишет на функциях, объяснить что ООП удобнее.
Пример простой и жизненный: функция сортировки, которая принимает в аргумент функцию сравнения.
Естественно, проще один раз написать функцию, которая будет использовать функцию сравнения, которую она на данный момент не знает, чем каждый раз под каждый класс писать свою мега-супер-пупер реализацию qsort под свой класс.
Вам на каком языке? )))
Например, какая-нибудь сортировка в массиве. Надуманный, но всё же пример:
usort($aArray, function($a, $b) {
    if ($a['field'] == $b['field'])
    {
        return $a['another'] < $b['another'];
    }
    else
    {
        return $a['field'] < $b['field'];
    }
});
чаще всего в PHP я использую lamda-функции в автолоадерах

<?php

$classmap = array(
     'Namespace\Class' => 'Path/To/Class.php',
);

spl_autoloader_register(function($classname) use $classmap {
    if (isset($classmap[$classname])) {
        include $classmap[$classname];
    }
});
UFO just landed and posted this here
вот интересная вещь, с одной стороный, эти лямбда-функции. а с другой — как часто кто-то использует сейчас конструкции типа:
$x = function( $number ) {
return $number * 10;
};
echo $x(8);
функциональное-ведь
А вот если взять какой-нибудь более жизненный пример, например работа с коллекциями или атрибуты классов — то ни элементу массива, ни атрибуту класса присвоить такую функцию нельзя. А делать награмождения с invoke и прочее — как то уже не красиво
спасибо за ссылку. это те же самые magic methods и прямого присваивания вниутри класса нету — по этому сложно назвать этот метод рабочим.
Что значит «прямого присваивания внутри класса нету»?

$o = new stdClass();

$o->x = function( $number ) {return $number * 10;};
$y = $o->x;
echo $y(100).PHP_EOL;


Или я вас не так понял.
<?class MyClass
{
$this->callback = function()
{
return 'hello';
}
}

может это не самый лучший стиль, но тем не менее
ВЫ про определение свойств в классе?
class MyClass
    {
    public $callback  = function( $number ) {return $number * 10;};
    }

Да, так нельзя. В php, в принципе, в качестве значений свойств при инициализации могут быть только константы.
Возможно вопрос будет глупым, но что мешает объявление лямбда-функции вынести в конструктор?
Ничто, но всё равно не получится написать
<?php
class MyClass {
  public $callback;  
  public function __constructor() {
     $this->callback  = function($number) { return $number * 10; };
  }
}
$obj = new MyClass();
echo $obj->callback(1);

PHP Fatal error: Call to undefined method MyClass::callback() in — on line 9 :(
<?php
     class MyClass {
         const member = 1;
         
         public $member;
         
         public function member () {
             return "method 'member'";
         }
         
         public function __construct () {
             $this->member = function () {
                 return "anonymous function 'member'";
             };
         }
     }
     
     header("Content-Type: text/plain");
     
     $myObj = new MyClass();

     var_dump(MyClass::member);  // int(1)
     var_dump($myObj->member);   // object(Closure)#2 (0) {}
     var_dump($myObj->member()); // string(15) "method 'member'"
     $myMember = $myObj->member;
     var_dump($myMember());      // string(27) "anonymous function 'member'"
?>
Спасибо, я в курсе, что пространства имён методов и свойств в PHP не общее :(
Хотелось бы видеть в примерах какие-то комментарии к коду.
В каком смысле? В его исходниках вроде комментариев к коду хватает. В отличие от обсуждаемого поста.
ой, это я с комментарием промахнулся. извените
в любом случае на сайлекс стоит обратить внимание интересующимся лямбда-функциями, по-скольку прокт очень интересный в этом плане
Можно наводящий вопрос? Какими должны быть комментарии в вашем понимании?
class QueryBuilder extends Builder { // название класса

$builder = new QueryBuilder(); // создаем экземпляр класса

Так? Мое мнение — код должен сам себя комментировать. Если есть кои-то сложный кусок кода, тогда да… и то, можно выносить в функцию с «соответствующим» названием.

Согласитесь, что писать после каждой функции ее перевод или что она делает — нет смысла.

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

Согласитесь, что писать после каждой функции ее перевод или что она делает — нет смысла.


Здесь я имел в виду не описание самой функции, а комментарий после ее использования…
echo "Hi"; // выводим "Hi"
Вы абсолютно правы, что построчное комментирование ни к чему.

Я бы хотел коммент перед каждым блоком кода (можно даже в основном тексте статьи) — что и как он делает, для решения какой задачи предназначен; почему в нем удобна анонимная, а не именованная функция. Это ведь сильно повышает читабельность: если мы заранее знаем задачу, то, действительно, какой там именно регэксп уже не имеет ключевого значения. Сухие пояснения автора в конце (после того, как мы прорвались сквозь код неизвестного назначения) — это не лучшая идея.
После прочтения вашего комментария таки да, захотелось видеть комменты на счет ± подхода для решения конкретной задачи.
Я всегда в этом месте «"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])» плачу Т_Т
Хорошая статья об языке программирования складывается из двух показателей: Полезной информации о конструкции языка и полезных примеров. Опционально — из интересных выводов в обсуждении. Вы не справились ни с первым, ни со вторым. Даже обсуждение бессмысленно. Подумайте, и исправьтесь
UFO just landed and posted this here
Новички это уже видели, уверяю вас.
Та и не вижу ничего плохого в "*", главное думать, где ее использовать…
UFO just landed and posted this here
Я потому и написал, что надо думать, а не пихать ее везде, где есть селект.
К примеру, если у меня есть справочник, струкрура которого (id,name) — ну никогда меняться не будет, и мне нужны 100% столбцов, чем плох подход?
UFO just landed and posted this here
Мы не о скорости разработки говорим. Еще пример — вывод содержимого таблички (пример чисто выдуманный, но такое ведь может быть) — всех полей как есть. Добавили новое поле (или изменили старое )- замечательно, оно сразу и выводится, без правки кода.

Так что тут можно долго спорить. Я остался при своем — иногда можно использовать, когда это удобно?

Хотя в общем случае вы правы, лучше перебрать поля чем делать выборку ненужных данных
А чего это он выдуманный? PhpMyAdmin его использует, что в принципе логично.
Я использую SELECT * как раз в тех случаях, когда знаю, что кол-во столбцов будет меняться, дабы не переписывать несколько раз один и тот же код. С одним ограничением — использую это только в функциях, которые загружают полный объект из базы (в CRUD — обёртках).
Холливар на тему: можно использовать иногда vs никогда нельзя использовать. Похожая тема: eval.
ничего плохого в разумном использовании * нету.
про самодокументирование кода ничего не могу сказать, но насчет всего остального, пожалуй, возражу.
не сразу обнаруживаемая ошибка при добавлении столбца — забавно, т.к. почти в любом случае при добавлении столбца приходится менять запросы на запись/апдейт. шансы не отловить изменения равны в обоих случаях
если дергаются все 100 полей — то наличие сотни полей в таблице — это проблема проектирования базы.
если возникают проблемы с порядком следования столбцов — значит стоит что-то пересмотреть и использовать fetch_assoc

есть подозрение, что вы работали с достаточно сложным чужим индусским кодом.
> UPD Говоря о том самом длинном регулярном выражении, я не стал подписывать его в комментариях и решил вынести сюда. Оно лишь ищет строки в одинарных и двойных кавычках, а так же имена таблиц и экранирует их.

Не трогая тему замыканий, скажу лишь что парсить на части Sql (тем более регулярками) — глупое и бесперспективное занятие. А необходимость экранирования/вставки параметров в запросы отлично решается плейсхолдерами, примерно так:

$data = $dal->getMany('SELECT * FROM ?table WHERE ?# = ?', array($table, $fieldName, $fieldValue));

Или даже такого:

$updateData = array('field1' => 10, 'field2' => 11);
$dal->execute('UPDATE ?table SET ?set WHERE ?# = ?', array($table, $updateData, 'id', $id));
Над переименовать топик в «Лямбда-функции и регулярные выражения» ;)
Пока вижу использование лямбда-функций как ещё один способ (когда удобный, когда нет, функции всё же в php не «граждане первого класса» или как там говорится) задавать callback — сортировки, мэппинги, редусы и т. п.

А вот в каких случаях стоит применять замыкания, когда они облегчают разработку — так и не понял (и не только PHP это касается)…
если пример ориентирован на новичков, то наличие регулярок не слишком положительно влияет простоту понимания кода. для новичков можно было бы и генерацию строк типа «Hello, world!» описать или что-то в таком духе
Нет, почему же, лучше поздно чем никогда. Просто не хотелось ограничиваться обычными примерами, а хоть как-то разнообразить описания этого явления. Но, несомненно, будущих статьях я учту все комментарии, особенно касательно примеров и документирования кода.
public function __construct($prefix='' ) {
$this->query = $query;
$this->prefix = $prefix;
}

Что то тут не так…
Sign up to leave a comment.

Articles