Pull to refresh

Comments 26

Кстати, еще пара забавных особенностей. К сожелению сейчас под рукой 5.3 нет, поэтому немного на память:

class Foo {
    public function bar()
    {
        $foobar = function($someshit) use ($this) {
            // ...
        }
    }
}


Работать не будет, не можем мы передавать $this, в замыкание.

Мое мнение почему так (скажу чесно в исходники не лазял, сужу только с точки зрения разработчка) — замыкания в пыхе — это что-то очень похожее на обычный класс с но с новым методом __invoke(). Класс кстати этот нам ни для создания ни для наследования не доступен. Такой вот оно, млин, замыкание…

И еще очень забавное поведение:
class Foo {

    protected $foobar;

    public function bar()
    {
        $this->foobar = function($someshit) {
            // ..
        }

        // Выдаст фатал еррор, так как метода foobar у нас в классе нет. А обращатся мы будем к нему ;)
        $this->foobar();
        
        // Тут уже будет все отлично и сработает анонимная функция.
        $foobar = $this->foobar;
        $foobar();
    }
}


И еще одна большая ложка дегтя:
class Foo {

    protected $foobar = function() {
        // ...
    }
}

Так же не работает.
use ($this) — смотри wiki.php.net/rfc/closures/removal-of-this

Далее замечание по коду — $this->foobar = function($someshit) {}; — обязательно точку с запятой.

по второму фрагменту — $this->foobar->__invoke() будет работать так же, а $this->foobar(); — имхо, совершенно обоснованно не будет.

protected $foobar = function() {}; — также не будет работать по понятным причинам: при присваивании начальных значений членам класса возможно использовать лишь константы.

«замыкания в пыхе — это что-то очень похожее на обычный класс с но с новым методом __invoke()» — не совсем верно понимаете. Замыкание — не класс, а объект встроенного класса Closure, у которого, действительно, есть метод __invoke(). Но значение этого метода в том, что он — т. н. «магический», т. е. вы можете написать:
class Foo {
  function __invoke() {
//..
  }
}
$foo = new Foo();
$foo();// вызывается $foo->__invoke();

Т. е. с этой точки зрения, замыкание — частный случай класса, реализующего магический метод __invoke().
use ($this) — смотри wiki.php.net/rfc/closures/removal-of-this
Читал, смотрел. Собственно

Далее замечание по коду — $this->foobar = function($someshit) {}; — обязательно точку с запятой.
не придирайтесь, не для компилятора пишу ;)

$this->foobar(); — имхо, совершенно обоснованно не будет.
Имхо совершенно необоснованно не будет. Собственно про $this и упомянул тут, потому как врядли кто подумает делать анонимную функцию статическую, а вот передавать $this — захочется очень и очень многим.

замыкания в пыхе — это что-то очень похожее на обычный класс с но с новым методом __invoke()» — не совсем верно понимаете. Замыкание — не класс, а объект встроенного класса Closure, у которого, действительно, есть метод __invoke().
Можно я попридираюсь? :) Замыкания — это объект класса? Круто. Может быть все такие замыкания — это объекты класса встроенного класса Closure с методом __invoke, который доступен нам, плюс рюшечки в виде use?
Не совсем понял вашу последнюю фразу. Тем не менее, я уверен в своих словах на 100%. Замыкание — объект встроенного класса Closure, не более и не менее. А «рюшечки в виде use» — всего лишь syntax sugar (пусть и очень удобный).
$ php -r 'var_dump(function(){});'
object(Closure)#1 (0) {
}
Тем не менее, я уверен в своих словах на 100%. Замыкание — объект встроенного класса Closure, не более и не менее.
Я про него и говорил. Правда класс с которым мы ничего не можем и сделать — не считаю обычным ;)

А «рюшечки в виде use» — всего лишь syntax sugar (пусть и очень удобный).
use с __invoke работает? Как-то не довелось попробовать…
Ничего не понимаю. Как это «класс с которым мы ничего не можем и сделать»? А $closure->__invoke() — это разве «ничего»? Или вы о том, что мы объект Closure не можем создать, используя new Closure()?

И вопроса я тоже не понял — насчет «работает ли use с __invoke».
new Closure; class MyClosure extends Closure {} — все это и еще кучу других вещей мы не можем с ним сделать, так что смысла от того, что это класс — немного.

$foo = function($bar) use($foobar) {}

Как такую же чтуку провернуть c __invoke?

closure в пыхе это все-же спец-синтаксис ;) а реализация такая для максимальной совместимости, могла быть и другая, но имхо эта неплохая… за что эту реализацию можно любить так вот за это:

function addOnRequest(Closure $callback)
{

}

имхо это вещь по сравнению с притянутым за уши «старым» подходом с псевдо-типом callback, который может быть и строкой и массивом и реальным калбеком от create_function… но старый код нужно будет переписать :)
function addOnRequest(Closure $callback)
{
$this->splObjectStorage->attach($callback);

return $this;
}

А? по моему очень даже :)
Очень-очень ;) Единственное что смущает, один вопрос — на обычный класс с __invoke ругаться будет?
чем, по моему это замечательно, типизация она на то и типизация, что-бы было «чОтко» ;)
Тем, что __ivoke — это не «вести себя как замыкание», а просто «прикинуться функцией».
именно, а теперь подумайте что такое замыкание, зачем оно нужно, и что значит для объекта в глобальном контексте «вести себя как замыкание»
Я знаю что такое замыкание и зачем оно нужно ;)

Я о том, что все таки реализация какая-то для меня немного неясная — есть класс Closure — который, мы трогать не можем, кроме как в тайпхинтинге — есть анонимная функция\замыкание с одной стороны. И есть возможность сделать практически тоже самое с помощью меджик метода __invoke:
class Foobar {
    function foo(Closure $closure) {
        $closure();
    } 
    function bar(SomeSlassWithInvoke $closure) {
        $closure();
    } 
}

Но это совершенно разные механизмы, нет, конечно это и в мануале ихнем написано - что с помощью этой чтуки объект просто прикидываеца функцией. Но вот народ воспринимает это немножко по другому...
ну не знаю, народ воспринимает это так как написано в мане, если честно когда читал вообще не провел параллели между __ivoke и замыканиями
Насчет «new Closure; class MyClosure extends Closure {}» — это поведение вовсе не уникально:
final class MyClass {
  private function __construct(){}
}

ну и насчет __invoke (если я вообще правильно понял, о чем речь)
$bar = 1;
$foo = function($x) use ($bar){
        echo $bar."-".$x."\n";
};
$foo(2);// prints 1-2
$foo->__invoke(2);// prints 1-2
по последнему примеру, а вот за это я люблю пых, в мане хрен знает с какой версии написано — константы и дефолтные значения только скаляры (по ману — статические значения) и не ипет. (а Closure это таки да объект класса)

как только можно будет задавать не скаляры в качестве дефолтных значений так ваш пример думается сразу заработает
ололо, в питоне это все уже сто лет работает, т.к. там изначально функции — first class citizens
(можно начинать минусовать...)
создается впечатление, что многие новые фишки пхп — чистой воды маркетинг
маркетинг? Мне каежтся что язык просто начинает облагораживаться…
т.е. питон это один большой маркетинг?
нет, я имел в виду, что в питоне эти вещи работают уже много лети, причем, как им положено в теории, а в пхп они работают через костыли и подпорки… по этому я заключаю, что их добавили лишь для того, чтоб добавить пару строк в пресс-релизе, подогреть угасающий интерес, ведь практической пользы едва ли больше нуля
Что именно в PHP работает через костыли и подпорки, думается у Вас предвзятое мнение, пописал и на пайтоне и на джаве, да, напрямую эти языки сложно сравнивать и не нужно, каждому нравится что-то, но мое сердце принадлежит пыху… а нововведения очень крутые на самом деле, ради фана сел переписывать свой велосипед на 5.3, конечно результат уже слабо похож на пых но многие вещи стали очень красивыми лаконичными и строгими («строгость форм» это то, кстати, что мне очень нравилось в джаве но очень не хватало в питоне)
ну то же use(...) в объявлении лямбды — есть костыль… В питоне (да что там говорить, даже в js) автоматически захватывается весь outer scope.
Можно полюбопытствовать, о какой строгости идет речь? По моему таки питон строже (а уж жава и подавно), например в питоне вы не сделаете '1' + 2 а пхп — легко, только грошь цена той легкости, т.к. это только провоцирует баги.
Sign up to leave a comment.

Articles