Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130802 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 A26521A00BC for ; Fri, 8 May 2026 00:56:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1778201806; bh=/HLmNH2cnkzDjW9yFfaCMFRQrvzpENUKHY/RieEt1q4=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=B6eB/KqyHgB9MRELZnJZsm2wRhS1Abj8QCXrSViA+re17nCzNky9+YVEVo8ell42O glJF7tW4bgqe8xQ9ygajvpvGq7ZgaOP/BthgQ8Q07roXwd6FsArgIrBf/B0tugineu /2M0EDajCB/F5vpBOPPSThFvU7q9fgiM2d58zHEcVypw+OZa0sFJnGKqO3Uw8PiHjs B7kcRfAwG47RVBHGyhAL4kaQ7csg+1na3NoIl4K0YSTcPhclcl9PdYOE7n5tf6My4C gxE9MSGW+dAhXjrFODIcYT+7UtTVqeRHSqldkQag8MFEeZubIuEMaBxh07JoriihqK eArtab0isPWoQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 27D6018005D for ; Fri, 8 May 2026 00:56:45 +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,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-yw1-f176.google.com (mail-yw1-f176.google.com [209.85.128.176]) (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 ; Fri, 8 May 2026 00:56:31 +0000 (UTC) Received: by mail-yw1-f176.google.com with SMTP id 00721157ae682-7bdf6db2c70so1239647b3.3 for ; Thu, 07 May 2026 17:56:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1778201786; cv=none; d=google.com; s=arc-20240605; b=T+c2I+wJcYA8bB3lACRIbvESv/EipHXeB9xD8mGUF/6WDCqxijj29eEDpsEyPOtzJu iL3UKx8Vzsp7PBwI4ShJCKcZMsWViOtN7es4Buft8oEBYI+qFU2dY71WNjybQ/fk8rCQ bq//8cbLzk8bIy9wz4cSjUI5NQWArJA8k8MRsklbmOjCfl8Q9lnOG00IoAPdOPcQdJFF /x10SDpunaVf16cVGT5tSloJxW+dUG/DGB5PAawq34fqlgixuszc5+/a0YnR0mhL/qqA ncG49PZLfXVikM5MDXHi6f4I7Dt8SF+nI691D9399Ho75eTXE8ZHt9KH8E9wtotI2xN4 2CFQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=72vPqTqJBqPzHapX1XF1dAHfqQq8uJRoQtprYb5TcJM=; fh=0un1hNQkIQnxRVmSrptHpYePKulyS9pFxhu85Wb7djM=; b=lFAVyJhkn9PrPBrCgS9htbgRE2cCDgyGA0q3ElpHc9kNEAZP95g6UIamLdw0a5WJzu 9Rh59q4Ew2GGJy8VzYc5RS8R1nrXsjpshxjQTc8wf+a9PMHv0K6x9aokfeaRNn966Q1p 23euCup4Fs9YqqRwSFtPv6fZUZvGZ3HTw09JV4cKbFUV7hDaQga9/ZhDSP9nFgWhc1SY HLgjW7WJrB8OwdQCm9Z5+cRuRhlIgzKJ2VzMVtGorSFbpg2dJd9KtM+IYF4VyydjBXvG BsSaGyGHvm1cFIRokSCSZXpZFlPrw37QBGqu1rQOhQ9eK/P2zVD9QjZtknk8Z1jyS8l6 9x6A==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778201786; x=1778806586; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=72vPqTqJBqPzHapX1XF1dAHfqQq8uJRoQtprYb5TcJM=; b=SA9gGQBuLXbHz4dKxwuQWT0nrg48b69ZcwN49NC93ZxSrIsk11tv76nRczfDABitYY yQZSHTLaX/8jCk77OYWKddnTBBkJn+rUbkGpRPwrON5p04Qr/HaLYWFo5t80n+TjnxNg 0+3qoiYTn5MtXjf9oWUaNSPSrsEOOQoOVQjFc6wTHzUIudRUHNSsj0lDW49SEME5HtW/ S+u2Npnr5csuQGC2t8ZnnkA5VtRbTC4zTwTTwSn36+k7Zw7BQDwBxg2p61CkuYTz2DtK nGoFhmiGhn9+4nKXgRAviTPmYXP+6K61cO0MrTYuSAYRZJhIy8GzUmDeNUvitIoAE+Hz T5rA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778201786; x=1778806586; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=72vPqTqJBqPzHapX1XF1dAHfqQq8uJRoQtprYb5TcJM=; b=DPtvDrNIm4sidJFdguY+AIoc6ll11+2YrilCVXjy/Xyw+ePnKlMljd5DDQSXW043KV wKEZ+yyXORX6UtEpsfbPEahhoEYhWqjjIqlL6YvPF5kIkjyqI9StXU+31uLj2awq9jCY di6yM7fEdx6CGguldZXPqWiLX2A0ToQ5JNGqrJwlvv490mAac9AsR4DtAKAfp/2B54Ss 1n7lyNt6BsMmUNhuZRctg2U5mRtEWtt0mYVOhpsavSM6XeyINwWmvXs51X2bf043TT10 dLWl/pefjrCmo3+Su5WpQe4Q0c0WY6HGALG54Qo08pbvb7OHvPufW9n6wmNxC/HW+QVg 4fsg== X-Gm-Message-State: AOJu0YwiSWTyShCZ1lp/KhS/GwwcJ/XE0VG7SZ+aerire5L9qLtuwGDr gk4AV1azPWS6wa5Mgtd+ZjxFS95nJTudDT8+Gw8QUbLZWSR5F5bPiizEKYdCOrdr6FSoavhp+LD ytvLictE4XuvTXDzUcmUzUfeVDvIbVotTjtQa X-Gm-Gg: Acq92OEfCMzm1tvt65DcxBHDyuRoMF8s0UnmPUXp0+DYY1KwbrvwnLqVnZm0Izvqa2S 3u+3mb+0nw9T0V88AxucRApqmmfZx0vngA3cB2mNM+pDny6aeIcmcw1i4L03Ox99CCExSD24JHF bWlF86lLtkNQtZpIu0IPMkJ1XhUMQM8L80PhtnlG1knVDGDoSeaw6T0bFS9+jd0XJlpz4lRSIXu 7h2/js55il52NYNEcYqCRVzLRKP3p/B68nklY+OVBJmLAxR8TqLYWvdp2vBjQnrr1Qq71l3N+lY hMPQkS4PaLumV0VicZc= X-Received: by 2002:a05:690c:d94:b0:7b2:59c0:ced2 with SMTP id 00721157ae682-7bdf945f004mr62704017b3.7.1778201786190; Thu, 07 May 2026 17:56:26 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: <0187D382-80FD-432C-B0D5-B0F9D8783419@hotmail.com> <6B83B07A-0344-4149-BFE9-7F3DD21BBA39@rwec.co.uk> <82D0F837-81DA-48D5-B467-35A8CCF52F9B@hotmail.com> In-Reply-To: Date: Thu, 7 May 2026 21:56:15 -0300 X-Gm-Features: AVHnY4JvrnsRaAIbfKOLG_4uJ0Mmm0MQbDtE0M-T-B0Z4uXAoBOrkzLMmcgyhu0 Message-ID: Subject: Re: [PHP-DEV] [RFC] Scope functions To: "Rowan Tommins [IMSoP]" Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary="000000000000ce11b4065143dd46" From: deleugyn@gmail.com (Deleu) --000000000000ce11b4065143dd46 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Thu, 7 May 2026 at 19:03 Rowan Tommins [IMSoP] wrote: > On 07/05/2026 13:16, Bob Weinand wrote: > > 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 > variables in a html or sql snippet with proper escaping, definitely great= . > > To me, macros should meaningfully transform their contained code rather > than wrapping a bit of logic around, which would be covered by this RFC. > > It's complimentary, not a replacement. > > > Thinking about this further, I agree that full-blooded macros would be > overkill for this case, but my starting point was that closures don't > feel like the right solution either - they're a different feature being > bent into shape. > > So rather than starting with a Closure, and taking things away, I was > trying to think of ways to start with a simple block of code, and build > it up. > > > For instance, the array_walk example in the RFC is just an ugly (and > probably inefficient) way of writing a foreach loop: > > array_walk($numbers, fn($number) { > $count =3D bcadd($count, '1'); > $sum =3D bcadd($sum, $number); > }); > > foreach($numbers as $number) { > $count =3D bcadd($count, '1'); > $sum =3D bcadd($sum, $number); > } > > So, what would it look like to generalise that, so we could do the same > for other scenarios, like async() and transaction()? > > > A simple first step would be something that could take a block of code, > and say when to execute it: > > custom_block transaction($dbConnection) { > try { > $dbConnection->beginTransaction(); > __execute_block_body(); > } > catch (\Throwable $e) { > $dbConnection->rollbackTransaction(); > throw $e; > } > $dbConnection->commitTransaction(); > } > > transaction($myDb) { > $myDb->query('UPDATE ...'); > } > > If the block body is never represented as a variable, there's no need to > define what happens when it outlives scope, or the user tries to clone > it, rebind it, etc. > > And if the calling code doesn't look like it's creating a Closure, users > won't have any wrong expectations about variable scopes or lifetimes. > > > Onto that, we can add syntax to push values into the block, e.g. using > the "as" keyword like in "foreach" (example based on the "Generator > decorator managers" section at the end of the Context Managers RFC): > > custom_block opening($filename) { > $f =3D fopen($filename, "r"); > if (!$f) { > throw new Exception("fopen($filename) failed"); > } > try { > __execute_block_body($f); > } finally { > fclose($f); > } > } > > opening(__FILE__ as $f) { > var_dump($f); > } > > > And some way to pull values out, e.g. a "break with" keyword: > > custom_block transaction(DBConnection $conn) { > $conn->beginTran(); > try { > if (__execute_block_body() =3D=3D=3D DBConnection::TRANSACTION_ABORT= ) { > $conn->rollbackTran(); > return; > } > } catch (\Throwable $e) { > $conn->rollback(); > throw $e; > } > $conn->commitTran(); > } > > transaction($connection) { > $affectedRows =3D $connection->query("UPDATE ..."); > if ($affectedRows =3D=3D=3D 0) { > break with DBConnection::TRANSACTION_ABORT; > } > // ... > } That looks like a function (aka closure) with a lot of weird extra steps. It=E2=80=99s been years, several proposals and multiple demonstrations on h= ow arrow function syntax can be expanded to be useful with multi-statements. So much gymnastics goes on to deny such a simple and elegant syntax. > --000000000000ce11b4065143dd46 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Thu, 7 May 2026 at 19:03 Rowan Tommins [IMSoP] <imsop.php@rwec.co.uk> wrote:
<= blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l= eft:1px solid rgb(204,204,204);padding-left:1ex" dir=3D"auto">On 07/05/2026= 13:16, Bob Weinand wrote:
> 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= variables in a html or sql snippet with proper escaping, definitely great.=
> To me, macros should meaningfully transform their contained code rathe= r than wrapping a bit of logic around, which would be covered by this RFC.<= br> > It's complimentary, not a replacement.


Thinking about this further, I agree that full-blooded macros would be
overkill for this case, but my starting point was that closures don't <= br> feel like the right solution either - they're a different feature being=
bent into shape.

So rather than starting with a Closure, and taking things away, I was
trying to think of ways to start with a simple block of code, and build it up.


For instance, the array_walk example in the RFC is just an ugly (and
probably inefficient) way of writing a foreach loop:

array_walk($numbers, fn($number) {
=C2=A0=C2=A0 =C2=A0 $count =3D bcadd($count, '1');
=C2=A0=C2=A0 =C2=A0 $sum =3D bcadd($sum, $number);
});

foreach($numbers as $number) {
=C2=A0=C2=A0 =C2=A0 $count =3D bcadd($count, '1');
=C2=A0=C2=A0 =C2=A0 $sum =3D bcadd($sum, $number);
}

So, what would it look like to generalise that, so we could do the same for other scenarios, like async() and transaction()?


A simple first step would be something that could take a block of code, and say when to execute it:

custom_block transaction($dbConnection) {
=C2=A0=C2=A0 =C2=A0 try {
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0 $dbConnection->beginTransaction();
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0__execute_block_body();
=C2=A0=C2=A0 =C2=A0 }
=C2=A0=C2=A0 =C2=A0 catch (\Throwable $e) {
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0$dbConnection->rollbackTransactio= n();
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0 throw $e;
=C2=A0=C2=A0 =C2=A0 =C2=A0}
=C2=A0=C2=A0 =C2=A0 =C2=A0$dbConnection->commitTransaction();
}

transaction($myDb) {
=C2=A0=C2=A0 =C2=A0 $myDb->query('UPDATE ...');
}

If the block body is never represented as a variable, there's no need t= o
define what happens when it outlives scope, or the user tries to clone
it, rebind it, etc.

And if the calling code doesn't look like it's creating a Closure, = users
won't have any wrong expectations about variable scopes or lifetimes.

Onto that, we can add syntax to push values into the block, e.g. using
the "as" keyword like in "foreach" (example based on th= e "Generator
decorator managers" section at the end of the Context Managers RFC):
custom_block opening($filename) {
=C2=A0=C2=A0 =C2=A0 $f =3D fopen($filename, "r");
=C2=A0=C2=A0 =C2=A0 if (!$f) {
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0 throw new Exception("fopen($filename= ) failed");
=C2=A0=C2=A0 =C2=A0 }
=C2=A0=C2=A0 =C2=A0 try {
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0__execute_block_body($f);
=C2=A0=C2=A0 =C2=A0 } finally {
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0 fclose($f);
=C2=A0=C2=A0 =C2=A0 }
}

opening(__FILE__ as $f) {
=C2=A0=C2=A0 =C2=A0 var_dump($f);
}


And some way to pull values out, e.g. a "break with" keyword:

custom_block transaction(DBConnection $conn) {
=C2=A0=C2=A0 $conn->beginTran();
=C2=A0=C2=A0 try {
=C2=A0=C2=A0 =C2=A0 if (__execute_block_body() =3D=3D=3D DBConnection::TRAN= SACTION_ABORT) {
=C2=A0=C2=A0 =C2=A0 =C2=A0 $conn->rollbackTran();
=C2=A0=C2=A0 =C2=A0 =C2=A0 return;
=C2=A0=C2=A0 =C2=A0 }
=C2=A0=C2=A0 } catch (\Throwable $e) {
=C2=A0=C2=A0 =C2=A0 $conn->rollback();
=C2=A0=C2=A0 =C2=A0 throw $e;
=C2=A0=C2=A0 }
=C2=A0=C2=A0 $conn->commitTran();
}

transaction($connection) {
=C2=A0=C2=A0 =C2=A0 $affectedRows =3D $connection->query("UPDATE ..= .");
=C2=A0=C2=A0 =C2=A0 if ($affectedRows =3D=3D=3D 0) {
=C2=A0=C2=A0 =C2=A0 =C2=A0 =C2=A0 break with DBConnection::TRANSACTION_ABOR= T;
=C2=A0=C2=A0 =C2=A0 }
=C2=A0=C2=A0 =C2=A0 // ...
}


That looks like a function (aka closure) with a lot of weird= =C2=A0extra steps. It=E2=80=99s been years, several proposals and multiple = demonstrations on how arrow function syntax can be expanded to be useful wi= th multi-statements. So much gymnastics goes on to deny such a simple and e= legant syntax.
--000000000000ce11b4065143dd46--