Comments 58
Что такое «лямбда-функции и замыкания» любой узнает открыв мануал. А ваши примеры настолько нереальны, что кроме как «WTF?!?!» мыслей в голову не приходит. Но даже это не главное. Главное то, что бел пол-литра в ваших примерах не разобраться.
Если бы все могли открыть мануал и во всем разобраться, то никому не нужно было вести блоги, писать статьи с примерами. Ну а примеры возможно да, с следующий раз я обязательно это учту
Ну как-бы в том и суть вопроса, что мануалы по php настолько интуитивно-понятны — что любой их может открыть и разобраться, и исключительно нежелание это делать порождает и огромное количество говнокода на 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 давно делать надо, во-вторых действительно не наглядно.
Вы думаете новички поймут вот это $regExp = '/([^{"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])*"|{[^}{]+})/'?
Я, например, с первого взгляда тоже понять не могу что делает эта регулярка, но для того, чтобы понять механизм работы с ними — это абсолютно не важно
ох уж это размножение зубочисток…
Приведите, пожалуйста, примеры которые показывают что да, лямбда-функция классная вещь и как это делать без лямбда-функции.
А то, напоминает как пытаются человеку, который все время пишет на функциях, объяснить что ООП удобнее.
А то, напоминает как пытаются человеку, который все время пишет на функциях, объяснить что ООП удобнее.
Пример простой и жизненный: функция сортировки, которая принимает в аргумент функцию сравнения.
Естественно, проще один раз написать функцию, которая будет использовать функцию сравнения, которую она на данный момент не знает, чем каждый раз под каждый класс писать свою мега-супер-пупер реализацию qsort под свой класс.
Естественно, проще один раз написать функцию, которая будет использовать функцию сравнения, которую она на данный момент не знает, чем каждый раз под каждый класс писать свою мега-супер-пупер реализацию 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];
}
});
вот интересная вещь, с одной стороный, эти лямбда-функции. а с другой — как часто кто-то использует сейчас конструкции типа:
$x = function( $number ) {
return $number * 10;
};
echo $x(8);
функциональное-ведь
А вот если взять какой-нибудь более жизненный пример, например работа с коллекциями или атрибуты классов — то ни элементу массива, ни атрибуту класса присвоить такую функцию нельзя. А делать награмождения с invoke и прочее — как то уже не красиво
$x = function( $number ) {
return $number * 10;
};
echo $x(8);
функциональное-ведь
А вот если взять какой-нибудь более жизненный пример, например работа с коллекциями или атрибуты классов — то ни элементу массива, ни атрибуту класса присвоить такую функцию нельзя. А делать награмождения с invoke и прочее — как то уже не красиво
Почему нельзя? Можно!
Но с вызовом функции, которая является свойством, будут некоторые проблемы: stackoverflow.com/questions/4535330/calling-closure-assigned-to-object-property-directly
Но с вызовом функции, которая является свойством, будут некоторые проблемы: stackoverflow.com/questions/4535330/calling-closure-assigned-to-object-property-directly
спасибо за ссылку. это те же самые 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';
}
}
может это не самый лучший стиль, но тем не менее
{
$this->callback = function()
{
return 'hello';
}
}
может это не самый лучший стиль, но тем не менее
ВЫ про определение свойств в классе?
Да, так нельзя. В php, в принципе, в качестве значений свойств при инициализации могут быть только константы.
class MyClass
{
public $callback = function( $number ) {return $number * 10;};
}
Да, так нельзя. В php, в принципе, в качестве значений свойств при инициализации могут быть только константы.
спасибо. не знал
Возможно вопрос будет глупым, но что мешает объявление лямбда-функции вынести в конструктор?
Ничто, но всё равно не получится написать
PHP Fatal error: Call to undefined method MyClass::callback() in — on line 9 :(
<?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'"
?>
Хотелось бы видеть в примерах какие-то комментарии к коду.
Обратите внимание на проект Silex
В каком смысле? В его исходниках вроде комментариев к коду хватает. В отличие от обсуждаемого поста.
ой, это я с комментарием промахнулся. извените
в любом случае на сайлекс стоит обратить внимание интересующимся лямбда-функциями, по-скольку прокт очень интересный в этом плане
в любом случае на сайлекс стоит обратить внимание интересующимся лямбда-функциями, по-скольку прокт очень интересный в этом плане
Можно наводящий вопрос? Какими должны быть комментарии в вашем понимании?
Так? Мое мнение — код должен сам себя комментировать. Если есть кои-то сложный кусок кода, тогда да… и то, можно выносить в функцию с «соответствующим» названием.
Согласитесь, что писать после каждой функции ее перевод или что она делает — нет смысла.
В примерах автора, как многие заметили, самое сложное — регулярки. Но расписывать о том, что они делают смысла особого нет, т.к. к теме это мало относится…
class QueryBuilder extends Builder { // название класса
…
$builder = new QueryBuilder(); // создаем экземпляр класса
Так? Мое мнение — код должен сам себя комментировать. Если есть кои-то сложный кусок кода, тогда да… и то, можно выносить в функцию с «соответствующим» названием.
Согласитесь, что писать после каждой функции ее перевод или что она делает — нет смысла.
В примерах автора, как многие заметили, самое сложное — регулярки. Но расписывать о том, что они делают смысла особого нет, т.к. к теме это мало относится…
Согласитесь, что писать после каждой функции ее перевод или что она делает — нет смысла.
Здесь я имел в виду не описание самой функции, а комментарий после ее использования…
echo "Hi"; // выводим "Hi"
Вы абсолютно правы, что построчное комментирование ни к чему.
Я бы хотел коммент перед каждым блоком кода (можно даже в основном тексте статьи) — что и как он делает, для решения какой задачи предназначен; почему в нем удобна анонимная, а не именованная функция. Это ведь сильно повышает читабельность: если мы заранее знаем задачу, то, действительно, какой там именно регэксп уже не имеет ключевого значения. Сухие пояснения автора в конце (после того, как мы прорвались сквозь код неизвестного назначения) — это не лучшая идея.
Я бы хотел коммент перед каждым блоком кода (можно даже в основном тексте статьи) — что и как он делает, для решения какой задачи предназначен; почему в нем удобна анонимная, а не именованная функция. Это ведь сильно повышает читабельность: если мы заранее знаем задачу, то, действительно, какой там именно регэксп уже не имеет ключевого значения. Сухие пояснения автора в конце (после того, как мы прорвались сквозь код неизвестного назначения) — это не лучшая идея.
Я всегда в этом месте «"\']+|\'(?:\\\\\'.|[^\'])*\'|"(?:\\\\"|[^"])» плачу Т_Т
Хорошая статья об языке программирования складывается из двух показателей: Полезной информации о конструкции языка и полезных примеров. Опционально — из интересных выводов в обсуждении. Вы не справились ни с первым, ни со вторым. Даже обсуждение бессмысленно. Подумайте, и исправьтесь
Новички это уже видели, уверяю вас.
Та и не вижу ничего плохого в "*", главное думать, где ее использовать…
Та и не вижу ничего плохого в "*", главное думать, где ее использовать…
Я потому и написал, что надо думать, а не пихать ее везде, где есть селект.
К примеру, если у меня есть справочник, струкрура которого (id,name) — ну никогда меняться не будет, и мне нужны 100% столбцов, чем плох подход?
К примеру, если у меня есть справочник, струкрура которого (id,name) — ну никогда меняться не будет, и мне нужны 100% столбцов, чем плох подход?
Мы не о скорости разработки говорим. Еще пример — вывод содержимого таблички (пример чисто выдуманный, но такое ведь может быть) — всех полей как есть. Добавили новое поле (или изменили старое )- замечательно, оно сразу и выводится, без правки кода.
Так что тут можно долго спорить. Я остался при своем — иногда можно использовать, когда это удобно?
Хотя в общем случае вы правы, лучше перебрать поля чем делать выборку ненужных данных
Так что тут можно долго спорить. Я остался при своем — иногда можно использовать, когда это удобно?
Хотя в общем случае вы правы, лучше перебрать поля чем делать выборку ненужных данных
Я использую SELECT * как раз в тех случаях, когда знаю, что кол-во столбцов будет меняться, дабы не переписывать несколько раз один и тот же код. С одним ограничением — использую это только в функциях, которые загружают полный объект из базы (в CRUD — обёртках).
Холливар на тему: можно использовать иногда vs никогда нельзя использовать. Похожая тема: eval.
ничего плохого в разумном использовании * нету.
про самодокументирование кода ничего не могу сказать, но насчет всего остального, пожалуй, возражу.
не сразу обнаруживаемая ошибка при добавлении столбца — забавно, т.к. почти в любом случае при добавлении столбца приходится менять запросы на запись/апдейт. шансы не отловить изменения равны в обоих случаях
если дергаются все 100 полей — то наличие сотни полей в таблице — это проблема проектирования базы.
если возникают проблемы с порядком следования столбцов — значит стоит что-то пересмотреть и использовать fetch_assoc
есть подозрение, что вы работали с достаточно сложным чужим индусским кодом.
про самодокументирование кода ничего не могу сказать, но насчет всего остального, пожалуй, возражу.
не сразу обнаруживаемая ошибка при добавлении столбца — забавно, т.к. почти в любом случае при добавлении столбца приходится менять запросы на запись/апдейт. шансы не отловить изменения равны в обоих случаях
если дергаются все 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));
Не трогая тему замыканий, скажу лишь что парсить на части 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 это касается)…
А вот в каких случаях стоит применять замыкания, когда они облегчают разработку — так и не понял (и не только PHP это касается)…
если пример ориентирован на новичков, то наличие регулярок не слишком положительно влияет простоту понимания кода. для новичков можно было бы и генерацию строк типа «Hello, world!» описать или что-то в таком духе
я немного опоздал с комментариями, правда?)
public function __construct($prefix='' ) {
$this->query = $query;
$this->prefix = $prefix;
}
Что то тут не так…
$this->query = $query;
$this->prefix = $prefix;
}
Что то тут не так…
Sign up to leave a comment.
Лямбда-функции и замыкания