Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129577 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id B7FC61A00BC for ; Tue, 9 Dec 2025 23:19:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1765322361; bh=lGX3HuNfgEhRxCF5NPVTBtNO9ai40Y8XfXNjmd/L/20=; h=Date:Subject:To:References:From:In-Reply-To:From; b=WkLRvRfsgFH0sLFJmfgZCQKnHWqpsxlvT0FCVs3dAsRKQLDKzs1URERCiaTtuRgtd tJxycoJry7cReU/p0p72iVZKVTjxEAzWCKG40Z2IOoUis1fPD9sQT7Gn9Z9ivurCJw UQ9i4rZWI9VdxEDuweSEy5CAUnsKROq+UVj/z73b/QoxcvJxvvYegEAdTxh1WPUNtc 6ytslBY3Y00uuSUnUEpqE20U5WhG8UJqXfivHVRK6U2iYXAw5hj5Bua5+h7oL9hh+x AHZcTUCR2pygRkl7jZ+pN7uZQUydd1S3A8OL42hordMAGWmarqF0tAREgg4RsKnmgu sdgsf3UTl6naw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 41E791805CE for ; Tue, 9 Dec 2025 23:19:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 9 Dec 2025 23:19:19 +0000 (UTC) Received: from phl-compute-04.internal (phl-compute-04.internal [10.202.2.44]) by mailfout.stl.internal (Postfix) with ESMTP id 0840A1D00197 for ; Tue, 9 Dec 2025 18:19:14 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-04.internal (MEProxy); Tue, 09 Dec 2025 18:19:14 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rwec.co.uk; h=cc :content-transfer-encoding:content-type:content-type:date:date :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm1; t=1765322353; x=1765408753; bh=LP/irQJg7tAcCHP4PgF5OVPJJ5XcnHz8QeOeDV0WsNA=; b= W8N5zh0yGaplJRyO9eOM5FOp2KtETon3P3KBz/KOToywh3cxa5+wD+lxgmPLfT7x huCyxsyDmnqsPs+6zGqbudDnIPiZzsnhzLtQ3cGo/6KAj9uaaNyUvaAcyoIFjoZz yq4PqdltbWNAbGYfKDi1K1qL8vWAibmsqdpc4XD6OvpRSP/C9qL8HysM1bWSZHxV PGHcWavcwAWk/rTbDtfZH9h37P9defvC7GeLFUeWxubbn+N6KK16m0o0Andp4bwe QYVsCI4wk8HI2ohsvXW5DFrNyQHQY9/15hbLLQ3dR8wHiZ5NzC6dybxAdJW2QhLf 7lV1Kye+h4ntU7NHjsS/4g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm1; t=1765322353; x=1765408753; bh=L P/irQJg7tAcCHP4PgF5OVPJJ5XcnHz8QeOeDV0WsNA=; b=abizaizBoy+5zgk/J bnbx49hXs73Q+LPi/nN/mxGGxHRjU66+pzRlfBVLUTb/wz0T9sdQT7ZrLgJWbe9K 1iEm3akwyPPid0r+JA0ny4FJQmUl2r97ywuXZYOjVC+ZoLX5YkSyV3IuItddgOZY Fpa5a76kauRkq2cCLL2fuWUG3ww7KqtoO6owNAo71UtDEkxchp4A4pCj5tWJuI/b zMKucd70/gKpslb9tTADVbWRhiCF2+MY0TCz6allp8dKlxN5mg5RMiIAVMzc6Zzn VBkLfDnhG8fjIrLMH0UGs7r7B5AX7Y1ycL8dJHQopIGo66+whB63TPyKln3KzJqL T09Xg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefgedrtddtgddvtdekhecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpuffrtefokffrpgfnqfghnecuuegr ihhlohhuthemuceftddtnecunecujfgurhepkfffgggfuffvfhfhjggtgfesthekredttd dvjeenucfhrhhomhepfdftohifrghnucfvohhmmhhinhhsucglkffoufhorfgnfdcuoehi mhhsohhprdhphhhpsehrfigvtgdrtghordhukheqnecuggftrfgrthhtvghrnhepudevie etgeffkeeffeehiefhjedugfetfeehtdffhfetvefhtdekgfekjefhueehnecuffhomhgr ihhnpehgihhtlhgrsgdrtghomhdpohhpvghnjhgukhdrohhrghdpmhhitghrohhsohhfth drtghomhenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhm pehimhhsohhprdhphhhpsehrfigvtgdrtghordhukhdpnhgspghrtghpthhtohepuddpmh houggvpehsmhhtphhouhhtpdhrtghpthhtohepihhnthgvrhhnrghlsheslhhishhtshdr phhhphdrnhgvth X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Tue, 9 Dec 2025 18:19:13 -0500 (EST) Message-ID: Date: Tue, 9 Dec 2025 23:19:12 +0000 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] Examples comparing Block Scoped RAII and Context Managers To: internals@lists.php.net References: <26a2f13c-f318-4d6c-9595-bfaaebcbabcb@rwec.co.uk> <78bfa50ad7c5111a1c6caaff3a525255@bastelstu.be> Content-Language: en-GB In-Reply-To: <78bfa50ad7c5111a1c6caaff3a525255@bastelstu.be> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") On 27/11/2025 08:34, Tim Düsterhus wrote: Hi Tim, As promised, I eventually got back to this e-mail properly, and have updated the examples in response. For convenience, here's the link again: https://gitlab.com/imsop/raii-vs-cm > > The block scoping RFC has been updated to `let()`. Updated. > 1. > > For db-transaction/implementation/1-raii-object.php I'd like to note > that it is not necessary to proxy execute() through the transaction > object. It could also be used as a simple guard object which only > purpose is to be constructed and destructed. That's true. The "wikimedia-at-ease" example illustrates that style, because there aren't any methods we'd want there at all. The drawback I see is that on a longer block, you have to come up with a name for that unused variable, and make sure you don't accidentally unset or overwrite it. Apparently Java's workaround for that is to allow "unnamed variables", which have the expected lifetime, but can't be accessed: https://openjdk.org/jeps/456 try-with-resources is given as one of the example use cases ("var" infers the type; "_" in place of the name makes it an "unnamed variable"): try (var _ = ScopedContext.acquire()) {     ... no use of acquired resource ... } Notably, this is *not* the same meaning for "_" as, say, C#, where "_ = foo()" tells the compiler to discard the return value of foo(): https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/discards In the case of a transaction, it feels logical for at least the commit() and rollback() methods to be on the Transaction class, but other methods would be a matter of style. I've removed execute() to take the simplest route. > > 2. > > The RAII object in 'file-handle' serves no purpose. PHP will already > call `fclose()` when the resource itself goes out of scope, so this is > existing behavior with extra steps. The same is true for the > 0-linear-code example in file-object. You don't need the `fclose()` > there. This is true as long as nothing stores an additional reference to the file handle. Having a separate "guard object" doesn't fully prevent this - a reference to the guard object itself could leak - but does make it less likely. It also gives somewhere to customise the open and close behaviour, such as adding locking, or converting false-on-error to an exception (more on that below). To see what it looks like, I've added a "file-handle-unguarded" scenario, which exposes the handle much more directly: it doesn't force fclose(), and leaves the application to handle the failure of fopen() The CM example benefits from being able to "break" out of the using{} block; as far as I can see, the current RFC doesn't allow that from a let{} block, is that correct? > > 3. > > The docblock in locked-pdf/application/2-context-manager.php is > incorrectly copy and pasted. Well spotted. Fixed. > I was about to comment that the 'file' examples were not equivalent, > because the context manager and IOC ones didn't include the error > logging, until I noticed it was hidden away in the implementation. > This probably suggests that I implicitly expected to see all relevant > control flow. Exception handling and logging in particular probably > greatly depend on the surrounding context to be useful (e.g. to adapt > the log message or to enhance it with additional context data). So > while it might superficially look cleaner / simpler, I feel that this > kind of generic handling will bite you sooner or later. So with the > context manager example, I would expect the “exception introspection” > capability to be used to properly tear down the context, but not for > cross-cutting concerns such as logging. That's a reasonable comment. Looking at those examples more closely, I realise I actually messed up the error handling in most of them - they never check for the false returned by fopen() I've moved the logging out into the "application", but updated all the "implementations" to throw a "FileOpeningException" if fopen() returns false. This really demonstrates the value of the "try using() { ... }" short-hand Larry & Arnaud have added to the CM RFC - we need the try to be on the *outside* of the block to catch the new exception. I presume a similar "try let() { ... }" could be added to yours? It's interesting how similar the example end up for simple scenarios, but I think if we had block-scoped variables, I'd still like Context Managers for some of the more complex cases. -- Rowan Tommins [IMSoP]