Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:118131 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 72448 invoked from network); 30 Jun 2022 10:29:00 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 30 Jun 2022 10:29:00 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A836918037E for ; Thu, 30 Jun 2022 05:20:30 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.6 required=5.0 tests=BAYES_00,BODY_8BITS, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, NICE_REPLY_A,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-wr1-f48.google.com (mail-wr1-f48.google.com [209.85.221.48]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 30 Jun 2022 05:20:30 -0700 (PDT) Received: by mail-wr1-f48.google.com with SMTP id v9so11444757wrp.7 for ; Thu, 30 Jun 2022 05:20:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=message-id:date:mime-version:user-agent:subject:content-language:to :references:from:in-reply-to:content-transfer-encoding; bh=kgAvyCesdL/2m4qKJM9ezmpLhjcbU6XUg7vCy5Z5s2E=; b=WnVW1YjUidy/dfIhYH4spEw8rq3WvEyWvO2TKMyN9AOiNKYacROGC1sgCHTAdTwF7j vYuq25bUzeEVO/NeC0boIkuzVdb3iIMa54uqxa+U/fEnFA6M6VN4WBGKWc/OJ9lTcYSN Azpdy6t0xZKdOKoKvAgJDwCnczc6ojavZZLhAXUDbOvZ5QLyriDiW4rO369C79BIooRo hxGMwqU4tcz8dyq5j7zwCxa5waLdfofhwfYK86alXehLJVU4V0p2nm/2P5kAmHS3tvFQ F7y19fJGIHXwfQVG8+fj/OSyjIWRbJtgnurfH9QapRc7AAbvhnAcAf2/o+XWYtLnAjBK BqPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:references:from:in-reply-to :content-transfer-encoding; bh=kgAvyCesdL/2m4qKJM9ezmpLhjcbU6XUg7vCy5Z5s2E=; b=HCaJqCymUVPckeWn7XrCt7TUTw3Bh+Mezx+5AFXxS6jdmxc6VVtECvZNhj4b62aYH5 VxGQu3aPLoOxiJGoNCWflTErMW6j6jeLtA7y8DfXAgV0GxWTvPanWs5rHdirHYfU9Li1 r3A/vaZCzaFFL7CqWYdLlvfM8ZYNxILRS66pX6v9wWc1Rvm47Vu2A7z54CSm5JZrAyus 81zYmhDJws8aZdkaWreagXtFjHiXMWKkjSrzI1Muy9L3u2uojeKp+vbI96Q6v0oGSctq KqLRMlyC2iIkDxPElVm+yyFD+nwCvabWRy0pzFeNRqgcstuPwSfPndTUKVTifYxuMvme I/uQ== X-Gm-Message-State: AJIora8zeuJzFwliVIQAhPiLxAxkj5EiJ8aJP2+5MmXeoFXMsNUB1riA KhRMXFOSR83TyDY50csUN90Tf3ulmHQ= X-Google-Smtp-Source: AGRyM1vbEMhO41W0bm2PDgYPsM9+4nPhU2p8qa4z/wT4QXo7XcPHIScbdDFSzkZNB4xl91r03ChWRg== X-Received: by 2002:a05:6000:1a89:b0:21b:83aa:ebd5 with SMTP id f9-20020a0560001a8900b0021b83aaebd5mr8147562wry.476.1656591628939; Thu, 30 Jun 2022 05:20:28 -0700 (PDT) Received: from [192.168.0.22] (cpc104104-brig22-2-0-cust548.3-3.cable.virginm.net. [82.10.58.37]) by smtp.googlemail.com with ESMTPSA id r12-20020a05600c35cc00b003a04e900552sm2155281wmq.1.2022.06.30.05.20.27 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 30 Jun 2022 05:20:27 -0700 (PDT) Message-ID: <4a0cd65f-a1dc-f225-abfa-4f9dbf2c3491@gmail.com> Date: Thu, 30 Jun 2022 13:20:26 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.10.0 Content-Language: en-GB To: internals@lists.php.net References: <2b35605f-8da8-46b1-aec3-00bd1bfe47fd@www.fastmail.com> <84eb5551-cfaa-42e6-9a74-ae229d5e269c@www.fastmail.com> <4662986.3VsfAaAtOV@arnaud-t490> In-Reply-To: <4662986.3VsfAaAtOV@arnaud-t490> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Subject: Re: [PHP-DEV] [RFC] Short Closures 2, aka auto-capture take 3 From: rowan.collins@gmail.com (Rowan Tommins) On 30/06/2022 11:29, Arnaud Le Blanc wrote: > I feel that the RAII pattern aka SBRM / Scope-Bound Resource Management is not > relevant in PHP context, and I don't believe that it's commonly used in PHP or > in garbage collected language. I've used a simple version of the pattern effectively to implement transactions: if the Transaction object goes out of scope without being explicitly committed or rolled back, it assumes the program hit an unexpected error condition and rolls back. > One way the lifetime of a value could be extended is via a reference cycle. > These are easy to introduce and difficult to prevent or observe (e.g. in a > test or in an assertion). I would expect reference cycles to be pretty rare in most code, particularly when you're dealing with a value with a short lifetime as is involved in most RAII scenarios. The worst-case release of the cycle can also be made predictable by running gc_collect_cycles() > An other way would be by referencing the value > somewhere else. You can not guarantee that the lifetime of a value is > unaffected after passing it to a function. Surely the only way to avoid that is with something like Rust's "borrow checker"? Otherwise, any function that has a reference to something can extend the lifetime of that reference by storing it inside some other structure with a longer lifetime. Manually freeing the underlying resource then just leads to a "use after free" error. > Another factor that makes RAII un-viable in PHP is that the order of the > destructor calls is unspecified. Currently, if multiple objects go out of > scope at the same time, they happen to be called in a FIFO order, which is not > what is needed when using the RAII pattern [0][1]. I can imagine this would be a problem for some advanced uses of the pattern, but for a simple "acquire lock, release on scope exit" or "start transaction, rollback on unexpected scope exit", it's generally not relevant. > Other languages typically have other ways to explicitly manage the lifetime of > resources. Go has `defer()` [2]. Python has context managers / `with` [3], C# > has `using` [4]. `with` and `using` can be implemented in userland in PHP. My understanding is that C#'s "using" is indeed about deterministic destruction, but Pythons's "with" is a more powerful inversion-of-control mechanism. I would actually really love to have some version of Python's context managers in PHP, and think it would be a better alternative to closures in a lot of cases. For instance, a motivation cited in support of auto-capture is something like this: function doSomething($a, $b, $c) {    return $db->doInTransaction(fn() {        // use $a, $b, and $c        // roll back on exception, commit otherwise        return $theActualResult;    } } But this is actually quite a "heavy" implementation: we create a Closure, capture values, enter a new stack frame, and have two return statements, just to wrap the code in try...catch...finally boilerplate. The equivalent with a context manager would look something like this: function doSomething($a, $b, $c) {    with ( $db->startTransaction() as $transaction ) {        // use $a, $b, and $c        // roll back on exception, commit otherwise        return $theActualResult;    } } Here, the with statement doesn't create a new stack frame, it just triggers a series of callbacks for the boilerplate at the start and end of the block. No variables need to be captured, because they are all still available, and "return" returns from the doSomething() function, not the transaction wrapper. The explanation of how Python's implementation works and why is an interesting read: https://peps.python.org/pep-0343/ Regards, -- Rowan Tommins [IMSoP]