Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129699 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: by lists.php.net (Postfix, from userid 65534) id 39FDB1A00BD; Sat, 27 Dec 2025 15:46:59 +0000 (UTC) To: internals@lists.php.net Date: Sat, 27 Dec 2025 16:46:58 +0100 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 Idea] Generic Collection Notation for Iterables (array) Content-Language: en-GB References: <20251227152633.7EC311A00BD@lists.php.net> In-Reply-To: <20251227152633.7EC311A00BD@lists.php.net> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Posted-By: 86.92.4.88 Message-ID: <20251227154659.39FDB1A00BD@lists.php.net> From: jordikroon@me.com (Jordi Kroon) On 27/12/2025 4:26 pm, Jordi Kroon wrote: > Hi everyone, > > I would like to propose a new type in PHP: Generic Collection Notation > for Iterables (`array`). > > **The problem** > PHP provides several ways to represent sequences of values: > > - `array` > - `iterable` > - `Traversable` implementations > - `generators` > > While these constructs are fundamental to PHP, none of them allow the > developer to express **what type of values they yield or contain** at > the language level. > > > This leads to several issues: > - Static analysis relies heavily on PHPDoc annotations. > - Runtime type hints communicate structure but not intent. > - APIs lack self descriptive type information. > - Developers must duplicate type information across signatures and > documentation. > > **Example** > ```php > class UserService > { >     /** >      * @return User[] >      */ >     public function getAllUsers(): array >     { >         return [new User("Alice"), new User("Bob")]; >     } > >     /** >      * @param User $user >      * @param Role[] $roles >      * @return void >      */ >     public function saveRoles($user, array $roles): void >     { >         // Some database call >     } > } > ``` > > **The proposal** > Introduce parameterized iterable types using generic like syntax: > `array` > `iterable` > `Traversable` > `Generator` > > ```php > function processUsers(array $users): void { } > > function normalize(array $values): array { } > ``` > > Optionally we could also extend the new array syntax with this > functionality. > > ```php > function processUsers(User[] $users): void { } > > function normalize(string[] $values): string[] { } > ``` > > Key points: >  - The existing `array` type remains valid and unchanged. >  - `array` means an array whose elements are of type `T`. >  - The syntax is currently invalid in PHP and therefore does not > introduce a backward compatibility break. > > **Example** > ```php > class UserService > { >     public function getAllUsers(): array >     { >         return [new User("Alice"), new User("Bob")]; >     } > >     public function saveRoles(User $user, array $roles): void >     { >         // Some database call >     } > >     public function streamAllUsers(): Generator >     { >         yield new User("Alice"); >         yield new User("Bob"); >     } > >     public function iterateAllUsers(): ArrayIterator >     { >         return new ArrayIterator([new User("Alice"), new User("Bob")]); >     } > >     public function getUserProvider(): Traversable >     { >         return new ArrayIterator([new User("Alice"), new User("Bob")]); >     } > >     public function normalizeNames(iterable $names): > iterable >     { >         foreach ($names as $name) { >             yield trim($name); >         } >     } > } > ``` > > **Runtime semantics and enforcement** > The goal is that  `array`  and related iterable parameterizations > behave like other PHP types: if a value is passed or returned that > violates the declared type, a  `TypeError`  is thrown. > > The main question is when and how enforcement occurs for eager versus > lazy containers. > -   Checked on function argument receive, property assignment, and return. > -   Each element value is validated against  `T`. > There are two approaches, but only one gives strong runtime guarantees. > > Preferred behavior: > -   Validate on consumption when the iterable is iterated. > -   If a yielded element violates  `T`, throw  `TypeError`  at the point > of iteration. > > This mirrors the fact that  `iterable`  may be lazy and cannot be fully > validated up front. > > **Implementation** > I have basic C knowledge but I don't have much experience with Zend > Engine / PHP Core. However I am fully committed to: >  - Write and maintain the RFC document. >  - Test and write tests for the implementation or draft >  - Participate in discussions > - Collaborate with anyone willing to help with the implementation > > **Keys and additional parameters** > This proposal focuses on element types. Keys are intentionally out of > scope for the initial version. > > Possible follow up work could explore  `array`  and > `Generator`. > > **Next steps** >  - I would like to have hear any potential caveats. For example > regarding lazy loading. >  - If the RFC gains internal support, I will officially publish the > first initial draft of the RFC. >  - Whether supporting the shorthand `T[]` should be part of the initial > scope or a follow up >  - Whether supporting `TKey` should be part of the initial scope or a > follow up > > Kind regards, > Jordi Kroon Yes, I am fully aware https://wiki.php.net/rfc/generic-arrays exists. But since it's older date I was not sure if I had to revive the original or start a new. That said since PHP is becoming a more strict language, it became more relevant. And the original RFC doesn't mention anything regarding Traversables or other iterables. Though I would like to give my sincere for the work that has been done for the current RFC proposal.