Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129643 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 76BED1A00BC for ; Wed, 17 Dec 2025 19:59:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1766001602; bh=CjSlP8w3eLIzO06W/xjoHwBLNAHXUzYkF+paA5KvHrE=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=N/CiebGGSNmCGZLKXtguNuUsW6HWLhqxQMEowoVkDIYc7Q1d7HTREZ38fXRleIqWV xBZP6kb1lXkCerHV2y8nQUZVG3nVfdqCfFiH9xYAe3m5tyBEmtcb1L0X0xP2U7BlkZ mEyiKVc89P+uBg0GlqPRH3s8YL8p355r+802fBdAOou/UTeYVZtq7uNm4jx+jWnikm VPSw3e5NeQAjjFr6bGdsPMPLfdBOjx6oevLe1OHuMRxamID/vIUY1V+Pt9aC9/YDtR Ozz5e4UlcOwTIkNDgI7YdSbC/VX/Wlbq39X4FZdip5+m0rltC2+8xAJd+O5I/LwiU8 /q/Ejp9nSnUtQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4E3C61801EE for ; Wed, 17 Dec 2025 20:00: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=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from chrono.xqk7.com (chrono.xqk7.com [176.9.45.72]) (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 ; Wed, 17 Dec 2025 20:00:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bastelstu.be; s=mail20171119; t=1766001594; bh=rINKSa3QMpAXwBizYY8ef6HCCPy9OvQGXyGxOsfaCQI=; h=MIME-Version:Date:From:To:Cc:Subject:In-Reply-To:References: Message-ID:Content-Type:from:to:cc:subject:message-id; b=I+/IeZEmjD1HQH/1adPmeYnLn0T6a0JfLUhVupj5M0Ye2JtppGunYGChUaZdDSOnm d9Q4/5+KE0QFFPu4ojMTUUd8sFWvvzfYrZgfOO3OCJ11YAICPpoklJ/OQTPZlcuIbv kRCJeBmGDvtYHMjBGlfUiyNNLiAV1ne/pJISJ/I4KyppM71UKgRZUeBQD/n9+nPT4K 3bnWw31AAcjTLtA8lf7Qr+3MqCh/OPYnVtuK8t1+o1RXgrfSoYfLjM5xI1rCAfZPI4 Zv+M0qK7N1njKhfCbuk+Uwxwu0in5F6zMm9eQR46xi5w5PL1LLBpyPHl4tOG5Uf5h5 YxIaMMF+NlS5w== Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 Date: Wed, 17 Dec 2025 20:59:54 +0100 To: "Rowan Tommins [IMSoP]" Cc: internals@lists.php.net Subject: Re: [PHP-DEV] Examples comparing Block Scoped RAII and Context Managers In-Reply-To: References: <26a2f13c-f318-4d6c-9595-bfaaebcbabcb@rwec.co.uk> <78bfa50ad7c5111a1c6caaff3a525255@bastelstu.be> Message-ID: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit From: tim@bastelstu.be (=?UTF-8?Q?Tim_D=C3=BCsterhus?=) Hi Am 2025-12-10 00:19, schrieb Rowan Tommins [IMSoP]: > 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 Something that came to my mind would be that the semantics of `let()` already allow for the following to guarantee that a value stays alive for the entire block even if accidentally reassigned: class Scoped { public function __construct() { echo __METHOD__, PHP_EOL; } public function __destruct() { echo __METHOD__, PHP_EOL; } } echo "Before scope", PHP_EOL; let ( $scoped = new Scoped(), $scoped, ) { echo "Start of scope", PHP_EOL; $scoped = 'something else'; echo "End of scope", PHP_EOL; } echo "After scope", PHP_EOL; which outputs: Before scope Scoped::__construct Start of scope End of scope Scoped::__destruct After scope It is definitely on the more obscure end, but I believe it is reasonably easy to understand *why* it works when seeing that it does work. This semantics of redeclaring/shadowing variables within the same (not a nested!) scope is something that folks might also know from Rust to ensure that a temporary input stays alive for long enough without taking up a valuable variable name: // https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=e5c84849b529aab5c1a5033ddfde2870 fn get_bar() -> String { return "bar".to_owned(); } fn id(v: &str) -> &str { return v; } fn main() { let bar = id(get_bar().as_str()); println!("{:?}", bar); } This is not currently valid, as the String returned from `get_bar()` is destroyed at the semicolon, but a reference to it is still stored in `bar`. The following however would work: let bar = get_bar(); let bar = id(bar.as_str()); println!("{:?}", bar); Best regards Tim Düsterhus