Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129277 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 8D3AB1A00BC for ; Sun, 16 Nov 2025 22:32:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1763332382; bh=2BES6Z6HzV98Yvq9wUpQr17VqmzLdbY+Y7y5IMRMbzs=; h=Date:Subject:To:References:From:In-Reply-To:From; b=Ln30iv+UlL07PMO6jtbA5lGAs7mZIMBJv1lHMdb1pLhDo4Yq/ndIMKy8pHBGla5Lp /cxS/gdoA6nehkdEltMIwgWBN4wPit0WgP36v2wCyLl6GliuP5gFFqm5oHOb2em+GZ nJKylq4ys8lmPytCiuT1AbZNHncq3uUYWhhlNov/+WuOYuJbaF8Av0xCHFXVH1Ga2o gNHk1ai1TXcjYo2RZzqwSd+vJFH069k4khBkMx1gYfR7I4Hjcy+loW0KIatIJDerw2 9NOMtKYmpVQodaEczu0Y8sdlaurJedoziymdIkXI/2FjOYmVekn71G/nvktBQEonvW b0OKBQmX97EvQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6FBC718003F for ; Sun, 16 Nov 2025 22:33:01 +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=-2.8 required=5.0 tests=BAYES_00,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 fhigh-b1-smtp.messagingengine.com (fhigh-b1-smtp.messagingengine.com [202.12.124.152]) (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 ; Sun, 16 Nov 2025 22:33:01 +0000 (UTC) Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.stl.internal (Postfix) with ESMTP id 65A177A008A for ; Sun, 16 Nov 2025 17:32:55 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-05.internal (MEProxy); Sun, 16 Nov 2025 17:32:55 -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=fm3; t=1763332375; x=1763418775; bh=0zsKlSIm0FWtc5/y2xohbdhe0MKK68TZ7h6QTwBcu5Q=; b= FCbiPKGTr2Xv8VIZuTERyHfIEyMJMy1XgzRa6JZAYdXImna0h1PNda5G+IbGBqcO SK9x/9S1MH+GQhbY2p/RcmOvAVCXGNvWw/NBlay9y2PGMaGOimBtfbAe0fayyWUF cvJ+EyMjcgFHnI3W+iotzIr3fkEMYyt2rSuVSnnQ/8gRSTnUURadatUU4iIgZw26 qgmwaDhj4OGi9r7tL7s5arNpcl7PC0UirdLalOZgH9wU+KdmfJDXz4mJ31nJuZc9 HmQ2f8KqSr0pYr+uxbfLFc2dcHX51HDIqrG1bWuMHOdXLatEDzMOu/6SoA4mipsL FjeBzfhSqjWQIATHi77IxQ== 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=fm3; t=1763332375; x=1763418775; bh=0 zsKlSIm0FWtc5/y2xohbdhe0MKK68TZ7h6QTwBcu5Q=; b=luR6bWPdBVJA3xiGZ qpNQ1AYKZHK6DqDyeoxlsbagRtE09g3/EPS+6qcez7HIcC1W1ABp48+bxPYdpcyW pfwXeRiNdj1+98Pi3CoMbFdEpQeVxsaX15kLFqzzu+9/MYA0q1n3EmzAxRf0tUH9 QoskeDksQqwdrkx7Qb6mPIkoNfPFJ+du6XRo+atV7TyYklEbp+uWI3NecyL0ykcj hzoIgh/E7QhVafPoTT3i/9YzJdaHC5acpF+UlkmLCZt7RyZn/MYTt5f94Zq2+jO8 SgIx9vKMAI3+/JT0sY1InQEpmv42n4r7NSO3ndRFoI3juy5tjs7Zjn+ObYo1M9eY OtN7w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggddvudeijeelucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucenucfjughrpefkffggfgfuvfhfhfgjtgfgsehtkeertd dtvdejnecuhfhrohhmpedftfhofigrnhcuvfhomhhmihhnshculgfkoffuohfrngdfuceo ihhmshhophdrphhhphesrhifvggtrdgtohdruhhkqeenucggtffrrghtthgvrhhnpeefgf duieekiedukefhveevudevfedvffffffefgeehtdefveeileevgffhfefhgeenucffohhm rghinhepghhithhlrggsrdgtohhmpdhmihgtrhhoshhofhhtrdgtohhmpdhorhgrtghlvg drtghomhenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhm pehimhhsohhprdhphhhpsehrfigvtgdrtghordhukhdpnhgspghrtghpthhtohepuddpmh houggvpehsmhhtphhouhhtpdhrtghpthhtohepihhnthgvrhhnrghlsheslhhishhtshdr phhhphdrnhgvth X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Sun, 16 Nov 2025 17:32:54 -0500 (EST) Message-ID: <04bef76f-affa-4212-9e57-8b2416cd64c4@rwec.co.uk> Date: Sun, 16 Nov 2025 22:32:54 +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> Content-Language: en-GB In-Reply-To: <26a2f13c-f318-4d6c-9595-bfaaebcbabcb@rwec.co.uk> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: imsop.php@rwec.co.uk ("Rowan Tommins [IMSoP]") On 16/11/2025 15:29, Frederik Bosch wrote: > On Sat, 15 Nov 2025 23:11:44 +0000, Rowan Tommins [IMSoP] wrote: >> The Block Scoping RFC and the Context Manager RFC cover a lot of similar >> use cases, and a lot of the discussion on both threads has been >> explicitly comparing them. >> >> To try to picture better how they compare, I have put together a set of >> examples that implement the same code using both features, as well as >> some other variations, in this git repo: >> >> https://gitlab.com/imsop/raii-vs-cm > > > Another suggestion would be to follow the Java try-with-resources > syntax. It does not require a new keyword to be introduced, as with > the Context Manager syntax. Moreover, it aligns with current > try-catch-finally usage already implemented by PHP developers. > > try ($transaction = $db->newTransaction()) { >     $db->execute('UPDATE tbl SET cell = :cell', ['cell'=>'value']); > } I did have a look into that when somebody mentioned it earlier, and I believe it is almost exactly equivalent to C#'s "using" statement: - C#: keyword "using", interface "IDisposable", method "Dispose": https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using - Java: keyword "try", interface "AutoCloseable", method "close": https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html The main difference I've spotted is how it combines with other blocks. In Java, you can use the same block as both try-with-resources and try-catch: try ( Something foo = new Something ) {     blah(foo); } catch ( SomeException e ) {     whatever(); } In C#, you can instead use a statement version of using within any existing block: try {     using ( Something foo = new Something );     blah(foo); } catch ( SomeException e ) {     whatever(); } Both are very similar to RAII, but because both languages use non-immediate garbage collection, the method is separate from the normal destructor / finalizer, and other references to the "closed"/"disposed" object may exist. At the moment, I haven't included examples inspired by these, because I thought they would be too similar to the existing RAII examples and clutter the repo. But if there's a difference someone thinks is worth highlighting, I can add one in. > Any object that implements TryWithContext can be used with such > syntax. The function returns the exit context operation as callback. > > interface TryWithContext { >    public function tryWith(): \Closure; > } > I can't find any reference to this in relation to Java; did you take it from a different language, or is it your own invention? Either way, it looks like an interesting variation on the Python-based enterContext/exitContext. Do you have any thoughts on what it's advantages or disadvantages would be? > Rather auto-capture I'd suggest explicit complete scope capture, by > using the use keyword without parenthesis. This is a completely separate discussion I was hoping not to get into. Although I've personally advocated for "function() use (*) {}" in the past, I've used "fn() {}" in the "auto-capture" examples because it is the syntax most often proposed. It's irrelevant for this example anyway, so I've edited it out below. > For a transaction it might look like this. > > class Transaction implements TryWithContext { >     public function tryWith(): \Closure >     { >         $this->db->beginTransaction(); >         return function (?\Throwable $e = null) { >             if ($e) { >                 $this->db->rollbackTransaction(); >                 return; >             } > >             $this->db->commitTransaction(); >         }; >     } > } Looking at this example, it feels like it loses the simplicity of RAII without gaining the power of Context Managers. In particular, tryWith() as shown can't return a separate value to be used in the loop, like beginContext() can in the Python-inspired proposal. The class would have a separate constructor and tryWith() method, with no clear distinction. Making the cleanup function anonymous prevents the user directly calling dispose()/close()/__destruct() out of sequence; but it doesn't stop the object being used after cleanup, which seems like a more likely source of errors. Still, it's interesting to explore these variations to see what we can learn, so thanks for the suggestion. -- Rowan Tommins [IMSoP]