On Fri, Nov 24, 2023 at 11:27 AM Michał Marcin Brzuchalski
<michal.brzuchal...@gmail.com> wrote:
>
> Hi Robert,
>
> pt., 24 lis 2023 o 10:24 Robert Landers <landers.rob...@gmail.com> napisał(a):
>>
>> ...
>> You can also emulate this with:
>>
>> class Defer {
>>   private function __construct(private \Closure $callback) {}
>>   public function __destruct() { $this->callback(); }
>>   public static function _(\Closure $callback) { return new self($callback); 
>> }
>> }
>>
>> and use it like:
>>
>> function writeSomeStuff() {
>>   // open files
>>   $deferred = Defer::_($closeFiles(...));
>>   // do stuff
>> }
>>
>> So long as a reference exists to $deferred variable, the deferred
>> method won't be run. If the variable is local to the method/function
>> being run it, the deconstructor will be called after the function
>> returns.
>>
>> It isn't the most beautiful thing in the world, and easy to forget to
>> store the result of Defer, but it is handy sometimes.
>
>
> This is interesting which makes me thinking if forget to store it could be 
> prevented.
> I think requiring a ref could help with that:
>
> class Defer {
>   private function __construct(private \Closure $callback) {}
>   public function __destruct() { ($this->callback)(); }
>   public static function _(\Closure $callback, &$var) { $var = new 
> self($callback); }
> }
>
> $deferred = Defer::_($closeFiles(...), $foo);
>
> Without $foo there'd be an ArgumentCountError.
>
> Cheers,
> Michał Marcin Brzuchalski

Hey Michael,

Thinking about it some more, I think we can go even further than that
and actually implement defer (enjoying the code golf)!

function defer(mixed &$anchor, \Closure $deferred): void {
    if(is_resource($anchor)) {
        $anchor = new class($anchor) {
            public function __construct(public readonly mixed $resource) {}
        };
    }
    static $mapping = new WeakMap();
    $mapping[$anchor] = new class($deferred) {
        public function __construct(private \Closure $deferred) {}
        public function __destruct() { ($this->deferred)(); }
    };
}

function writeFiles() {
    $handle = fopen("/tmp/scratch.php", "wb");
    // todo: write data
    defer($handle, static function() use ($handle) {
        echo "\ndeferred\n";
        fclose($handle);
    });
    echo "\nafter defer()\n";
}

writeFiles();
echo "\nafter writeFiles()\n";

or something like that.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to