Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129188 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 752271A00BC for ; Mon, 10 Nov 2025 10:04:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1762769084; bh=rfIRkmGFnmJbAR85F523mQU8qMsa39oDVP0L46Zh9ls=; h=Date:From:Subject:To:References:In-Reply-To:From; b=c3bgFB1MEL7iO6BM3wPDKseFrOMF7iCtrKk0EoxEC/hgGz+hA7Ft2IDrmlgfNG1pI dU/rB5S8W14OAGS86ok4Te2QOIRDPVxmNyreO3ahiNShQ2gH731t8RJ1CP3rsPJlmv Wz+Acjjntp1TbFpUXuBEcqKD30bhF3VI2LT8fTdlVBSb3Kl17ae2T/TuR9vGexpln+ mn1ePtOwKvQ1WgIE3S6H1ink6A1JTvWtOMzEm4nJ9LwOF6JGl+vqeekiqhMwNIuyyx kRi4G2Jc2IkTbSHPL6XzwoGtd3Pn4qmICypnRy3oPYorisvGPDFBPrkJVU/cUb8tZF 8iqJaZySLhF6Q== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 1E66D180072 for ; Mon, 10 Nov 2025 10:04:43 +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.9 required=5.0 tests=BAYES_20,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 ; Mon, 10 Nov 2025 10:04:42 +0000 (UTC) Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfhigh.stl.internal (Postfix) with ESMTP id 2E6387A0172 for ; Mon, 10 Nov 2025 05:04:37 -0500 (EST) Received: from phl-mailfrontend-01 ([10.202.2.162]) by phl-compute-06.internal (MEProxy); Mon, 10 Nov 2025 05:04:37 -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=1762769077; x=1762855477; bh=tt4P9exJYoY43Xu4dGwiGFXwQfqui7PphwwxfjeU0E0=; b= nQog9PZvxkCGqVCxNvLedZUcr36Ydw/vEK1Dt+WYdYzHC6zVp8m/MrLpHB5ARA62 rLSXSHvxOQQ80N4zPDSCkRQ9jG6eiaUBXnaVlPqsK5j2NmOX05fTVEphfa5q0JdN cucLvETui4PW0Xrbe34tsFgHmNOtvGFDlmKx6eTmXWLOh2aOd3EpvvjhrY8Suln7 DBnk3vqNkafXQ5kHmf39U7JfGC76YuPnb3Da3BS6eMJ8W1sz0t1u8kgGGCRkzVtB E5fG7MeWeC/YH5S0Adl8AA4xrV6YIOttjbR+bkcUSQhw6mIkHY0O7yNvwWjp1V5Y rU1yWQzlm5f4VsPlWUFpeQ== 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=1762769077; x=1762855477; bh=t t4P9exJYoY43Xu4dGwiGFXwQfqui7PphwwxfjeU0E0=; b=uZkX9v8MbYrVdznCM d9tCCxtm6b7wnKAOcKguBbdPyUP3RD3hIMJbpbJNx54zMLan5Bqvrh2pP8BjzpS2 95wjBYH7LJXBWOY8tQI3x2n/zpkuEw613Ri+Zq8MRo6T5ufGfMs/AmAXuxTq9ZBB VIIbXXsudm341PwENWX3SggxrERPOaWfW13di47/qcMdnPH2nyF6Skj5mSpqRK5R Qlb2jGfb+PWooeisvZxSYvQ6A2n1/68RVeVNo0QDay7g4EZXvJkWtffOAkpcxY1w Ze6IawP0ohd9j+a0PMd6KWh1TSA52s+xPWPeWzxezq/OsFf2PNG+IkJ0/DOpiLHM w2jww== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduleektddvucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucenucfjughrpefkffggfgfhuffvfhgjtgfgsehtkeertd dtvdejnecuhfhrohhmpedftfhofigrnhcuvfhomhhmihhnshculgfkoffuohfrngdfuceo ihhmshhophdrphhhphesrhifvggtrdgtohdruhhkqeenucggtffrrghtthgvrhhnpefhve evvdelhfffveduffeivdehveelheekfeevuedufeegffekgfdtvdeihefhleenucffohhm rghinhepfihhrghtrdhnvghtpdguvghsthhruhgtthhorhhsrdhnvghtnecuvehluhhsth gvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepihhmshhophdrphhhphes rhifvggtrdgtohdruhhkpdhnsggprhgtphhtthhopedupdhmohguvgepshhmthhpohhuth dprhgtphhtthhopehinhhtvghrnhgrlhhssehlihhsthhsrdhphhhprdhnvght X-ME-Proxy: Feedback-ID: id5114917:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA for ; Mon, 10 Nov 2025 05:04:36 -0500 (EST) Message-ID: Date: Mon, 10 Nov 2025 10:04:35 +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] [RFC][Discussion] use construct (Block Scoping) To: internals@lists.php.net References: <1F3473C7-5D83-48D3-964E-A63D6F44D21E@rwec.co.uk> <4998b4c6-0474-4f0c-b63a-9909b8acfa96@bastelstu.be> Content-Language: en-GB In-Reply-To: <4998b4c6-0474-4f0c-b63a-9909b8acfa96@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 09/11/2025 16:52, Tim Düsterhus wrote: > We don't think so. Our goal with this proposal is - as the title of > the RFC suggests - making block scoping / limiting lifetimes of > variables more convenient to use. The goal is to make it easier for > developers and static analysis tools to reason about the code, for > example because variables are less likely to implicitly change their > type. Perhaps part of the problem is the comparisons the RFC calls on. It mentions features from three existing languages, none of which is about block scoping; and doesn't mention the ways other languages *do* indicate block scoping. In C#, all local variables must be declared before use, and are scoped to the current block; the "using" keyword doesn't change that. Instead, it is for a very specific purpose: correctly "disposing" what .net calls "unmanaged resources" - normally, raw memory pointers passed out from some non-.net library or OS call. While objects can have "finalizers" which work very like destructors, .net only guarantees that they will be run "eventually", when the object is garbage collected. The IDisposable interface, and the "using" keyword which makes use of it, exist to release the unmanaged resources at a deterministic moment. The Hack "using" statement is clearly inspired by C#, but takes it further: there are no destructors or finalizers, so the *only* way to perform automatic cleanup is implementing the IDisposable interface. The compiler then enforces various restrictions on that class: it can only be created as part of a "using" statement, and can only be used in such a way that it will be unreferenced after disposal. Unlike C#, Hack's local variables are normally function-scoped, so it is significant that disposal happens at the end of a block; but it is neither intended or usable as a general-purpose block scoping mechanism. The Python "with" statement is completely different. In the words of the PEP that specifies it, it is "to make it possible to factor out standard uses of try/finally statements". Like PHP and Hack, Python's local variables are function-scoped; but the with statement doesn't change that - if a variable is initialised in the "with" statement, it is still available in the rest of the function, just like the target of "as" in a PHP "foreach". The "with" statement isn't actually concerned with the lifetime of that variable, and in fact can be used without one at all; its purpose is to call "enter" and "exit" callbacks around a block of code. If what you're interested in is a general-purpose block scope, none of these are relevant examples. The most relevant that comes to my mind is JavaScript's "let", which is an opt-in block scope added to an exsting dynamic language. A comparison of that approach to what you propose here would be interesting. > Consider this example: > >     function foo() { >         $a = 1; >         var_dump($a); >         { >             var_dump($a); >             let $a = 2; >             var_dump($a); >         } >         var_dump($a); >     } > > What would you expect the output of each of the `var_dump()`s to be? Yes, this is a problem that any language with block-scoping has to tackle. Since there are many languages which have that feature, I'm sure plenty has been written on the pros and cons of different approaches.  I'm not aware of any language that requires a specific kind of block in order to introduce a new scope, but that doesn't mean it's a bad idea. The approaches I am aware of are: - Shadowing: At the point of declaration, any other variable with the same name becomes inaccessible, but not over-written. Result: 1, 1, 2, 1 - Forbidden shadowing: At the point of declaration, if there is another variable of the same name in scope, an error occurs. Result: 1, 1, Error (let statement must not shadow $a from outer scope) - Hoisting: The variable declaration can occur anywhere in the scope, and affects the whole scope even lines above it. Used by JavaScript's "var" keyword, and very confusing. Result: 1, 2, 2, 1 - Forbidden hoisting: The variable declaration can occur anywhere in the scope, but lines above that point are forbidden from accessing it. Used by JavaScript's "let" keyword, with the dramatic name "Temporal Dead Zone". Result: 1, Error (must not access block variable $a before declaration) -- Rowan Tommins [IMSoP]