Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130792 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 D2D501A00BC for ; Thu, 7 May 2026 12:16:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1778156197; bh=dbgJPTAZXxPtkp79TkU9KggyuxlA0ftsFfSpdI16Z18=; h=From:To:CC:Subject:Date:References:In-Reply-To:From; b=kkpsQntVEke9hEBMQXznzxZ1ShTWkyLhu9IDymN8wcSPlz9bxkjxZBVoZN4VbRb5j SRzA3uqrZp5w4J1tUVkz3PJHvGekkjEbCsTd1/3EHO307jHqEdiSxJI92wKUMrfvjD 0FQLtuJk6+HBZ1ih+tAK9qsnmAbJCjxTLUlbKhZXJOzyk4yqeQeQ/klNZk46GVCMAn asaXLYeG9Pb/UztpFZ7VuTiZzchWJPnzSbrejipaJHSZhYDttiWyJlLKfMFw9LxDh5 k6IWDks3Rv6rn4I77Fr4/0s2PDdyAVpX2kOVEEs1F8dCrovpEnu9ZfuFsBPVVC9uYH 9Di56EEV/I3eA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A334A180032 for ; Thu, 7 May 2026 12:16:36 +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.8 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS, FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from OLAP279CU001.outbound.protection.outlook.com (mail-norwayeastazolkn19011026.outbound.protection.outlook.com [52.103.51.26]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (secp384r1) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 7 May 2026 12:16:36 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=VZFv/3EG1/tTccmAAZ5JxRwuUZ2DY8TouqJ5UJTGIPYoKJ+X4erRMcCBKSnd0Y68Tgh+oau10ezSqLnoay+jge1TKsnXuT9pAA7mYCJCMHZMAmGk8dRqlPI0wK5Vnv8FKav1TVTo1t1yC9RX94b8MxYmix6V4YZlwHSXipLgaZmutYRa1alr0nyYGClwsBnuMPDtgmb4eh4AIUyALJ+eLtfNfX99f8+Ecu9CoP6SCGycO/iEGf1gwf6OgTl0Gt6UTsTdBT3PalbqwcZjRVRmTg64T+Ohry8fkde0c1qfZpUwmkzZSCxSBDYmm3l4JN1U+f/RlM+z/Y4XU3ZUCTUWMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=IpjfVa6mp7OoaO15T6KX+hODy8+cQ/mCeUGpSYJzgF4=; b=SLmiIzfMk/+HF10JIoQixj/3BN//F4NjNx6waWvhSEqZps1Be/kFB5YWCvJ0frMRH6KtJSDeuEHEPj4N9hhTPip0DqN555KauO1C2x9UITlr7KfkOZNE9CSiFS16Ccw9ySItBzdWTL1fsX+IeVy+2ZEZoL/BXdWn+4owz84UwgV31dSOChMhUi1b/ny4VBdzdSHFWCax2Pf2d8kIQK/B3bEKP9xNYNU/qElIZoSREaLvdiEeSqRXq6nFNxQfEsyirivDgDHCDdLYE508UjtWEvfBtxzw8tBAPvViuNBNpkR5QFjpHCWyVuIeHzEeYLjwXgJkvE/OMbaPx2ypBhuSRg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=IpjfVa6mp7OoaO15T6KX+hODy8+cQ/mCeUGpSYJzgF4=; b=Eh4Pu3qwSZA17OHbI/gFD2rYfcNk5PYHeCiY9SldM1jHQR2y1l2WSKYEYpav7xEac1E26jm8CHUVRQLMfBn9EpwEFwyIa9IZGcV5Ao2Mp1CK5ZVZzKTeup2mDo9QxErU/GGP8uakHrPMGGeYMukvh8ZcnJPXZ22Lbxit2hEM7FbOGED6q2+PX3qRvCCisGNM1BK1JuLav5zauGHjUXOr+sKXafEeKoybNdT408tYJfWKGc7p1lyu/EtJTRh7yvVmAl3YnGfkTUxAdjpajK5VWCB6NhDtZTvntaNUyzTE/XE6YuHAc2O6H0mwjYSDE+P3jnvnz9HR1BvlsDGna9aIQg== Received: from SVAP279MB0383.NORP279.PROD.OUTLOOK.COM (2603:10a6:f10:1f::6) by OSDP279MB1475.NORP279.PROD.OUTLOOK.COM (2603:10a6:e10:90::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9891.17; Thu, 7 May 2026 12:16:27 +0000 Received: from SVAP279MB0383.NORP279.PROD.OUTLOOK.COM ([fe80::adb8:fa3a:bf3a:1780]) by SVAP279MB0383.NORP279.PROD.OUTLOOK.COM ([fe80::adb8:fa3a:bf3a:1780%3]) with mapi id 15.20.9891.008; Thu, 7 May 2026 12:16:27 +0000 To: "Rowan Tommins [IMSoP]" CC: PHP internals list Subject: Re: [PHP-DEV] [RFC] Scope functions Thread-Topic: [PHP-DEV] [RFC] Scope functions Thread-Index: AQHc3ZRICnzqQPdB80mu1usLvIb05bYCZBkAgAAXWQA= Date: Thu, 7 May 2026 12:16:27 +0000 Message-ID: <82D0F837-81DA-48D5-B467-35A8CCF52F9B@hotmail.com> References: <0187D382-80FD-432C-B0D5-B0F9D8783419@hotmail.com> <6B83B07A-0344-4149-BFE9-7F3DD21BBA39@rwec.co.uk> In-Reply-To: <6B83B07A-0344-4149-BFE9-7F3DD21BBA39@rwec.co.uk> Accept-Language: de-DE, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: Apple Mail (2.3864.300.41.1.7) x-ms-exchange-messagesentrepresentingtype: 1 x-ms-publictraffictype: Email x-ms-traffictypediagnostic: SVAP279MB0383:EE_|OSDP279MB1475:EE_ x-ms-office365-filtering-correlation-id: 77cf4e24-4218-4f88-d2f6-08deac3276fd x-microsoft-antispam: BCL:0;ARA:14566002|31061999003|51005399006|25031999004|461199028|24021099003|12121999013|37011999003|15080799012|41001999006|8060799015|19110799012|8062599012|56899033|1602099012|40105399003|3412199025|4302099013|440099028|10035399007|102099032|19111999003|26104999009; x-microsoft-antispam-message-info: =?us-ascii?Q?MgFYRpbeaJmzSton3TZKTYL2wYrooargV7/jAcjETi83084ODiNN4Cu84j3w?= =?us-ascii?Q?yWWF5/UQ1q/mt45OHsn/QzmmTvwfFS9w1vEDI44T7Ygy0e6XrK4iGP7mu/kh?= =?us-ascii?Q?EosVTKuZIC94tPNLUxpE+xMKJR01HkYT702+xkBsvoJkQWTtheBs6JfGeTOL?= =?us-ascii?Q?9wwl5Ww4H3lXAR+jpOuRi12WUT/NzF2E9O7yciPnnstlpq86s7EN0J/Q+dXd?= =?us-ascii?Q?wD5kQtDiwc4vFn/16uRxP/cpdXTT0thcYLEQe+5NNv7gNGUE9A7nax3n/aq/?= =?us-ascii?Q?Z3s8h0tQH/IBsvA9f9mtPcUix4m4uoVLkuPIr0i8sPiCs0XSJ06OIC5j7VFw?= =?us-ascii?Q?aEWjO4pQHDB1TkrN8mahzi8ROs6uj5NUgsHwNQ8zzrE0TNuoNYyvnAEWwBBU?= =?us-ascii?Q?eDapvGRJnWBAMn8h8gvVYU/u/lZWeX0OThNSs/gBUcTlZvs79wFgLQDQDHYl?= =?us-ascii?Q?BWi8nL28wkZneCzPbAe+BhM4V/bqPgMZem69Z9LQ16hoj4myDE64iGkll6XY?= =?us-ascii?Q?PfA8zJjWNBRntwoISQ+Ip4+7e6afB+yaZmdKpWtNNWWiWL/7vE8LM6W9T4oK?= =?us-ascii?Q?oBxIX51NsS30E13yTjkM16YyQRDYubWDDpVJ/T/39lT4OgTsAVPWV2/d76wo?= =?us-ascii?Q?G0ee9j07ZXmLIYRXC4Ejm6UeftKC7vmM7X1wwKU0HMUCNdr8OlFwDDk4tpvP?= =?us-ascii?Q?N3S3k5CLO2z5Zh4LAnSeSVWWBIafd3+eAoch+NNTSrwED+7YUTJpj4vyBDyg?= =?us-ascii?Q?BnelOO+xk/mKIT0iRG9A5WFICDpplNDETUdamJOB1C+K/1qkrWqrKJ/qQtFA?= =?us-ascii?Q?zIU2kSiyHQNrW4VCymFb9Ov7zk4YFLzPO2/hVJhBWWu7Ubwu6bLQzpwvXqiy?= =?us-ascii?Q?uTS/xCX5cO0MV1SFX//dXMcVZeJbNdLdy5MdP39jrSV+MHnccUVlGbjyv7l4?= =?us-ascii?Q?i4ktJCE4a9LASM4zqOAzAphMeGxXE5Fy9K2CRrx9H/fVhmcz15ZunC7Jjg8L?= =?us-ascii?Q?1sUB+n5Ml2V/LFlIm8vZc47QwQAXUdGkv2kk9c81ey4XigBITNY9COfD85hU?= =?us-ascii?Q?QGX24gbH1F0XgfE0yVgVBnssTvsiLUSpBByEQWpsFuvG4h2L/MKu66KWCCO4?= =?us-ascii?Q?GcLYQHrWcAOe+U4lzjB4uFdzAj2CfC9yQg=3D=3D?= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?23HKGMlr18EDHMrrTbuXQ5okWRekaEzDZD7VHE6MJza1U023+8ZFCLzMX9hp?= =?us-ascii?Q?GPFczsa7VRWLNrBT/TeVFcAWZDu0GImMFSfS9CXc0PFhLdiyTyBWVoSPE315?= =?us-ascii?Q?wVtvfPK0ePXW7A0Pl/4fHW0dDOp/Wa5Uv2eLdP/aSm7RFCkm4rxGfL7R/Fdd?= =?us-ascii?Q?9TJW6xqPjbrW5h7U9fvO06+ETwi4pGscyDwnYBOg0cIpD5+VIlM6r1SMX/Hb?= =?us-ascii?Q?hIeJxaAuAA4iKexfeW4YTDGqpUuqmitEy1tG+eqmgyUv6AtR0lqNgCAi1wAQ?= =?us-ascii?Q?rs43dnEvmgyVbUqcbIF6L3Bktnn8IW7tr3oFUK9/EnB8kfyGbJmxQUubb39r?= =?us-ascii?Q?W/GfhL2pl+GB1Q0x3IBReMd64XBKTq3ISWE8v+HdCkvd4mueWNV1UA32h5AH?= =?us-ascii?Q?JIFakm5BN56Slg42oaNll4cImAyaffwVF2EbFpbMdT35L9iVTgslFUTMqVVm?= =?us-ascii?Q?+sLHAHgs19Ym7RpJo9W7/uG0qqlUwDafoTpMg1rHvUyhfhDhsaJ/XfrAqaPi?= =?us-ascii?Q?aLAOdvldbuENvvOJrtkl/BhOcVr5IUzIkpSYKpyPDQ94XnnTBb/kFx1bnifK?= =?us-ascii?Q?I3I4KmX164T5OqCXheeVo/c1Zz27EZkeAIRLS/+Na9PYfHl+tE0/OSepSrRP?= =?us-ascii?Q?4fKhPLHIg6dmTwf9+ShY2wujkbeI5gJC4L+mtpSwXAaGzgI8pulQVC+udOvQ?= =?us-ascii?Q?Om25u+e0pft/96I/RuFJyCLg5a9NJ36Sh8/94/NJx5Q0Xf0ihPnRES+20MNK?= =?us-ascii?Q?o3p1wRACIk1F7GLIrR0XI5LEiJfMsjS1e16Dix/SO1cxpwVl+Dv+25hrQAzW?= =?us-ascii?Q?QWaKzGY15I7Zg+joe7/HEMrmie3S6NOg+90VWdbfPHCpJpMpNbfI6tE/AZCt?= =?us-ascii?Q?KZCxudmmeswGHVV12uf3qo18mwuhG7yXwpju3cFYKdw8qJxZs9ennSVaDpO2?= =?us-ascii?Q?ODlhkiBGaZmmTOff6BVTu7QsXhM0J2nQxlJ178PIW9f82pzSqtvrDTQESGSW?= =?us-ascii?Q?iWdEjbOisCbiCutKxJsBwJkRO1vyiVkDCrftU9w3trUUlcqFcs7/pWu0nOrT?= =?us-ascii?Q?3h5aiiobJLo8wJX1eC21VlGVb2i2fVNPlY30VGFaOD802ZE/5GCa8cGMUIJ3?= =?us-ascii?Q?jR84FPBimNkPV0pT90F/XFzz0MPbuil6O64nEdah9bmBcu1E7OwjyWS96M5Z?= =?us-ascii?Q?dtQx7dDA5LxzEUgpw0JvsSljSwxLcZ/hlZakUJuvKCgaEBUtQKfwRnzKqYMw?= =?us-ascii?Q?BmjKTbvI1B3nS5IZ5BSpWS5tvB75lvFi1wqFLjEIcewbUjdwuWcYBO4CVvyI?= =?us-ascii?Q?idgvHNt2rynw0VDzDqOqypmxM6fXVspww3/+YuEYFzwanGnmnqbuxZ2VkV7A?= =?us-ascii?Q?fWS7nyzGoZaBfcLOobzxTmoBolL7vEOeG/64Ga0oDIJ99+nunzUY5Mfbvd8F?= =?us-ascii?Q?qp57HZ4Ds7lu09BkDF+OL1I9ow4cu4tB?= Content-Type: text/plain; charset="us-ascii" Content-ID: <5E13D6A6F9F54E41B075FB70FF599C5A@NORP279.PROD.OUTLOOK.COM> Content-Transfer-Encoding: quoted-printable Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 X-OriginatorOrg: sct-15-20-9412-4-msonline-outlook-ecede.templateTenant X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: SVAP279MB0383.NORP279.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: 77cf4e24-4218-4f88-d2f6-08deac3276fd X-MS-Exchange-CrossTenant-originalarrivaltime: 07 May 2026 12:16:27.7842 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: OSDP279MB1475 From: bobwei9@hotmail.com (Bob Weinand) Hey Rowan, > Am 07.05.2026 um 12:52 schrieb Rowan Tommins [IMSoP] : >=20 > On 6 May 2026 21:09:45 BST, Bob Weinand wrote: >> Volker and I drafted a RFC: >>=20 >> https://wiki.php.net/rfc/scope-functions >=20 >=20 > Hi Bob,=20 >=20 > An I right in thinking that this is essentially equivalent to "automatic = capture by closure", with an extra restriction on the lifetime of the resul= ting closure? It would be good to spell out in the RFC how this compares to= other approaches, and other languages. I think the closest thing to what we propose here is GCC Nested Functions: = https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html They have similar lifetime semantics - cannot outlive their declaration sco= pe and cannot be redeclared either (by design because they're named, but sc= oped function names like that are not a thing in PHP, hence we assign to a = variable). > In particular, JavaScript's capture semantics are somewhat notorious as a= source of confusion. A common example is creating closures in a loop which= all use the same variable; as far as I can see, the proposed semantics wou= ld allow this as long as they were executed before the parent scope ends: >=20 >=20 > ``` > function parent_scope() { > $values =3D range(1,10); >=20 > $scoped_functions =3D []; > foreach( $values as $v ) { > $scoped_functions[] =3D fn($v) { > echo "Chosen item is {$v}"; > }; > } >=20 > run_random_callable($scoped_functions); > } >=20 > /** > * @param callable[] $callables > */ > function run_random_callable($callables) { > $pick =3D array_rand($callables); > $callables[$pick](); > } >=20 > // Will always output 'Chosen item is 10'! > // The list of "scoped functions" will all actually refer to the same $v,= updated in the loop > parent_scope(); > ``` >=20 >=20 > I don't know if there's some way to make the lifetime even more restricte= d, so that the use cases of "immediate execution" are allowed, but this kin= d of code is not. Have you missed this following restriction and example in the RFC? > Re-evaluation: The same scope function declaration (same source code loca= tion) invalidates the previous instance. Should it still be called, an erro= r is raised. >=20 > Any scope closure is only allocated a single slot, preventing recursion a= nd double declaration. There are two choices: guaranteeing uniqueness (retu= rning the active Closure again) or invalidating the previous Closure. We ch= ose the second option to avoid the misconception that scope functions would= capture the current variables. E.g. in foreach loops, it will always print= the current active value and never the value at declaration time. >=20 > $closures =3D []; > for ($i =3D 0; $i < 3; $i++) { > $closures[] =3D fn() { return $i; }; > } > var_dump($closures[2]()); // int(3) > =20 > $closures[0](); // Error: Cannot call scope function: defining scope has = exited This restriction exists exactly because of that issue. > For something like "run this in a transaction", the closure is really act= ing like a poor man's "continuation": it creates two new stack frames (tran= saction wrapper, callback) when what you really want is to *interleave* the= boilerplate and the case-specific code. One thing which this does is interleaving with a well-defined boundary. ret= urn works and does not cross the whole function, just the callback. You don't get a sudden goto or break skipping some of your code. The intern= al variables of the wrapper frame are isolated and don't leak to you. Argum= ent values to the wrapper are properly type checked. > In that sense, hygienic macros are probably the "ideal" solution - everyt= hing is expanded inline into a single scope, and there's no Closure object = which can be misused. With "hygienic" you mean the macro has to produce full expressions, right, = i.e. not C preprocessor style. > Context Managers could in fact be implemented as such a macro, and as I u= nderstand it, the implementation is basically doing that internally by mani= pulating ASTs. >=20 > I wonder if there's any "minimal" macro system which would allow this kin= d of inline boilerplate expansion, without needing to design an entire meta= -language? You wonder rightly, but the main problem is the nature of the language/impl= ementation. How would you compile that? op_arrays are fixed at compile time and not going to change afterwards. So, you can either try calling functions at compile time to manipulate a fu= nctions code (let's say e.g. all !-suffixed function names get called at co= mpile time with some sort of token stream or AST, whatever) or invent very = clever hacks to somehow generate op_array snippets on the fly at runtime. That once-per-request nature of PHP also makes it very difficult to efficie= ntly cache such code (unless you assume every invocation of that function w= ill always output the same, which you cannot even rely on, because every re= quest could invoke a different file defining the same macro etc.). You will also get interesting behaviours with jumps, e.g. a goto will sudde= nly ... jump over a bunch of logic, so any macro will have to do try/finall= y. while loops inside that macros, do they count towards the break/continue= stack etc.? It's a big rabbit hole. You'll find that it's not impossible to do, but it = has quite a few trade offs and possibly odd choices to make. I am not opposed at all to such a consistent macro system though. ... but I would not make a transaction like that a macro. For inlining vari= ables in a html or sql snippet with proper escaping, definitely great. To me, macros should meaningfully transform their contained code rather tha= n wrapping a bit of logic around, which would be covered by this RFC. It's complimentary, not a replacement. Thanks, Bob=