Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130789 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 7DF6D1A00BC for ; Wed, 6 May 2026 22:26:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1778106412; bh=0cDcewWdYOQhc0pjQ7lthYfmyWjckLzWqou7sMFve80=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=kEl2jbi6adN3nJsiDYWBrkolNTrUXR9Pjtlxlu3nbsiQUaSBfXXrYaWSqp2UjvNk6 ydh9WCVFZQhya+Q7lKZLo5z56HRFQUzeFVh5REYAOHm2gVdBTucCCoKyQBi2UULUQU z1tppDU+I7NVyvWMPfFpON304Gq3XeNh2F7lK9OdMM3GldU29SYWGB7NZmrntCXPZR qarSkx1LSycRwHiFiPTlDB9xTDWrqu+t+BKEoOyMcw5yCy0ur7u3LhF/1ylpXvAbWk /P7utmSh924fX9oGQ6Gtwslc7gleQ6Axgnlh8pn5+gXfABr0x5NgN4aBwzi5ztOaMc LZhRn2v6VrzeQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2B143180077 for ; Wed, 6 May 2026 22:26:51 +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=1.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FORGED_GMAIL_RCVD, 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-wr1-f42.google.com (mail-wr1-f42.google.com [209.85.221.42]) (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, 6 May 2026 22:26:50 +0000 (UTC) Received: by mail-wr1-f42.google.com with SMTP id ffacd0b85a97d-43d73422431so177005f8f.2 for ; Wed, 06 May 2026 15:26:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778106405; x=1778711205; darn=lists.php.net; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=38Q1f2pZuGXCS3TZw6qwEyhxfPTKgG+PqhPDWkfQWRY=; b=K9r2YunkLhBC3AyQluEVRJY1pcLwfc3S0gWNllTxftPcDjqX6Fs2islB8Xit+HBtHn RLlkh0iLjAvR1xTo/6IafcZgCl+1RfJ8p5ngvINHtQoJ1kThF1iw19n72VKD4j8ozHSW TWDxEZ9xXPZN3FpuFbm8BodgnaXLQVQd23HdnzefW97337hLuiYGlEg2NoXNnb2NUken uDmlV+JwvezqNCAhgvsE4jTUQDO9KRR59yU9Fu/I7W9Af/0EQ43PlgbiKI8DXKi6sxv7 ozliZO3tGzVIaYATsP7WN/dNDJyn1E5SEJQcHb8b1MunM2O7j0WwYNDbrqNqybrFpjZt OIFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778106405; x=1778711205; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=38Q1f2pZuGXCS3TZw6qwEyhxfPTKgG+PqhPDWkfQWRY=; b=Mz2NDj1jrn650e357NuecIv3CbRei/z873viCay3bXn1ShHBH6bLJ7OyZ2nFZ2v2lp f1jc1YzT9caAwVrnV5znmfGOqLKS0E1RrisZgodWeAQ5jGab3QHLLgbFvW0HaFHe23Bo FDCwryQy0c6tb5MxYrYPT4Y5O0uM3ABanAeoXTo+AQK0qrEtgP8jD5DxZTZ3bS71OdKH 7h/6zpPUqtaC2VtGB54p6CSGffSqCHHAb4ylcxzqA8NsPqv1bHfu/g0exuyw8fLcU95c FOmK/HmCILn+yZBLcTTzz9NoT1II/unO24XaEabCOZq+QROG8Ff6yRI8G63T+gb+mKKC Yszw== X-Gm-Message-State: AOJu0Yw190UY+qSo7c6SSGKV5y0gJZ1CVfdkYf1QivcAYDTz12iZs5O9 i6QHrkT4b6abGDn2Lm6uA6WqhHLdl+lJ4NWaWYguTwv2p/FnlOa/j1b7 X-Gm-Gg: AeBDiesQszpMlaa9DlVPG3NN0C64eMdF+OEz5oaH5G1cZFrAp0v/gCB7RLCUvGAa9tk wNL+LvVoCJGiYcAABVCAHj6m2eA5cuWLTUrVskKO0ROI3u0Etb6TjBOMnLLY7BMye6s0PfMEKGB L4HNwkLPUnM+2iCon3SqrA+H0BkScGkKaiCu/20Ej34KhvA4eHjY0Chky9cdh26coq4G4IlzwXN aFcm8Ihn63IOQ9L9Z5+K5tc/iqLd7tt02DfcgV31rb4MA9kPPjeRw9Srpt2IvKfiuK7etZoX2F8 vIMATgr+l6Yv9QKrniyiRxChJ3yE8nShsrzW1EOFhiVluPRA7LECZSMnZ85VXATqSFY2BD9REmi AQW+M7vRb6aTzS5R60x45ISVjpjn/WDU54hRoYE8IunZIO53JO2bRdnnGTNjVuw//ouyz4fNX7/ bVae3GUZgCGsq/X03SaRJ0BPT0xcO2NZH2ISi/0GOLqsDGKtignZ2qM26r+IhiuqxP88g= X-Received: by 2002:a5d:5846:0:b0:44a:75e2:558d with SMTP id ffacd0b85a97d-4515d9a07damr8591702f8f.41.1778106404418; Wed, 06 May 2026 15:26:44 -0700 (PDT) Received: from smtpclient.apple ([89.249.45.14]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45054b03e04sm15494059f8f.21.2026.05.06.15.26.43 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 06 May 2026 15:26:43 -0700 (PDT) Message-ID: <2B8D1475-4FF2-467E-88C0-0538EAD2576E@gmail.com> Content-Type: multipart/alternative; boundary="Apple-Mail=_450B0F35-C625-4CFB-BE9C-5F655F58FCB0" Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: [PHP-DEV] [RFC] Scope functions Date: Thu, 7 May 2026 00:26:33 +0200 In-Reply-To: <0187D382-80FD-432C-B0D5-B0F9D8783419@hotmail.com> Cc: PHP internals list To: Bob Weinand References: <0187D382-80FD-432C-B0D5-B0F9D8783419@hotmail.com> X-Mailer: Apple Mail (2.3864.400.21) From: claude.pache@gmail.com (Claude Pache) --Apple-Mail=_450B0F35-C625-4CFB-BE9C-5F655F58FCB0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > Le 6 mai 2026 =C3=A0 22:09, Bob Weinand a =C3=A9cr= it : >=20 > Volker and I drafted a RFC:=20 >=20 > https://wiki.php.net/rfc/scope-functions >=20 > Please consider it and share your feedback. >=20 > I hope it will alleviate pain around some of the most common forms of = Closure usage which is "execute this now as part of the called = function", which currently can require a lot of "use ($variables)". >=20 > For me the primary use case of use ($capturing) was always "I need = this function later and want to explicitly document what escapes my = function". This, however, required this straightforward usage of = Closures to also document every single usage of a variable. Which is = really not that beneficial at all. >=20 > Thus the scope functions as proposed will be able to fill that gap in = future.=20 >=20 > Thank you, > Bob Hi, This is nice. As I understand it, this RFC could resolve problems that = the Context Managers RFC tries to resolve in a simpler and more flexible = way. (And it resolves other problems too, of course.)=20 Taking the first example from the Context Manager RFC: ```php using (file_for_write('file.txt') =3D> $fp) { foreach ($someThing as $value) { fwrite($fp, serialize($value)); } } // implementable as: function file_for_write(string $filename): ContextManager { return new class($filename) implements ContextManager { function __construct(private readonly string $filename) { } private $fp; =20 function enterContext() { $this->fp =3D @fopen($this->filename, 'w'); if (!$this->fp) { throw new \RuntimeException('Couldn=E2=80=99t open = file'); } return $this->fp; } function exitContext(?\Throwable $e =3D null): ?\Throwable { @fclose($this->fp); return $e; } }; } ``` This can be rewritten as: ```php file_for_write('file.txt', fn($fp) { foreach ($someThing as $value) { fwrite($fp, serialize($value)); } }); // implementable as (which is simpler: one function instead of a whole = class): function file_for_write (string $filename, callable $do_write): void { $fp =3D @fopen($filename, 'w'); if (!$fp) { throw new \RuntimeException('Couldn=E2=80=99t open file'); } try { $do_write($fp); } finally { @fclose($fp); } } ``` For those of us that abhor exceptions in case of recoverable failure, = there is even more. With this RFC, one can easily return true/false (or = whatever other signal) for success/failure, while Context Manager = strongly leans towards the use of exceptions (although, of course, it = remains possible to assign the outcome to a variable and to exit the = context with `break` or `goto`): ```php $ok =3D file_for_write('file.txt', fn($fp) { foreach ($someThing as $value) { if (something_is_wrong_with($value)) return false; fwrite($fp, serialize($value)); } return true; }); // implementable as (which is more flexible: exceptions are not the only = type of signal): #[\NoDiscard] function file_for_write (string $filename, callable $do_write): bool { $fp =3D @fopen($filename 'w'); if (!$fp) { return false; } try { return $do_write($fp); } finally { @fclose($fp); } } ``` =E2=80=94Claude --Apple-Mail=_450B0F35-C625-4CFB-BE9C-5F655F58FCB0 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

Le 6 mai 2026 =C3=A0 22:09, Bob Weinand = <bobwei9@hotmail.com> a =C3=A9crit :

Volker and I drafted a RFC: 

https://wiki.php.net/rfc= /scope-functions

Please consider it and share your feedback.

I hope it will alleviate pain around some of the most common forms = of Closure usage which is "execute this now as part of the called = function", which currently can require a lot of "use = ($variables)".

For me the primary use case of use ($capturing) was always "I need = this function later and want to explicitly document what escapes my = function". This, however, required this straightforward usage of = Closures to also document every single usage of a variable. Which is really not that beneficial at all.

Thus the scope functions as proposed will be able to fill that gap = in future. 

Thank you,
Bob
=


Hi,

<= div>This is nice. As I understand it, this RFC could resolve problems = that the Context Managers RFC tries to resolve in a simpler and more = flexible way. (And it resolves other problems too, of = course.) 

Taking the first example from = the Context Manager = RFC:

```php
using = (file_for_write('file.txt') =3D> $fp) {
    = foreach ($someThing as $value) {
        = fwrite($fp, serialize($value));
    = }
}

// implementable = as:

function file_for_write(string = $filename): ContextManager {

    = return new class($filename) implements ContextManager = {

        function = __construct(private readonly string $filename) { = }

        private = $fp;
        
    =    function enterContext() {
      =       $this->fp =3D @fopen($this->filename, = 'w');
            if = (!$this->fp) {
            =     throw new \RuntimeException('Couldn=E2=80=99t open = file');
            = }
            return = $this->fp;
        = }

        function = exitContext(?\Throwable $e =3D null): ?\Throwable {
  =           = @fclose($this->fp);
          =   return $e;
        = }
    = };
}
```

This can be = rewritten = as:

```php
file_for_write('file.tx= t', fn($fp) {
    foreach ($someThing as $value) = {
        fwrite($fp, = serialize($value));
    = }
});


// implementable = as (which is simpler: one function instead of a whole = class):

function file_for_write (string = $filename, callable $do_write): void {
    $fp =3D = @fopen($filename, 'w');
    if (!$fp) = {
        throw new = \RuntimeException('Couldn=E2=80=99t open file');
    = }
    try {
        = $do_write($fp);
    } finally {
  =       @fclose($fp);
    = }
}
```

For those of = us that abhor exceptions in case of recoverable failure, there is even = more. With this RFC, one can easily return true/false (or whatever other = signal) for success/failure, while Context Manager strongly leans = towards the use of exceptions (although, of course, it remains possible = to assign the outcome to a variable and to exit the context with `break` = or `goto`):

```php
$ok =3D = file_for_write('file.txt', fn($fp) {
    foreach = ($someThing as $value) {
if = (something_is_wrong_with($value))
        =     return false;
        = fwrite($fp, serialize($value));
    = }
    return = true;
});

// = implementable as (which is more flexible: exceptions are not the only = type of = signal):

#[\NoDiscard]
functi= on file_for_write (string $filename, callable $do_write): bool = {
    $fp =3D @fopen($filename = 'w');
    if (!$fp) {
      =   return false;
    }
    = try {
        return = $do_write($fp);
    } finally {
  =       @fclose($fp);
    = }
}
```


=E2=80=94Claude



= --Apple-Mail=_450B0F35-C625-4CFB-BE9C-5F655F58FCB0--