Re: [RFC Idea] Generic Collection Notation for Iterables (array<T>)
| From: | Jordi Kroon | Date: | Sat, 27 Dec 2025 15:46:58 +0000 |
| Subject: | Re: [RFC Idea] Generic Collection Notation for Iterables (array<T>) | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-129699@lists.php.net to get a copy of this message | ||
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<T>). **The problem** PHP provides several ways to represent sequences of values: -array-iterable-Traversableimplementations -generatorsWhile 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**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<T>iterable<T>Traversable<T>Generator<T>function processUsers(array<User> $users): void { } function normalize(array<string> $values): array<string> { }Optionally we could also extend the new array syntax with this functionality.function processUsers(User[] $users): void { } function normalize(string[] $values): string[] { }Key points: - The existingarraytype remains valid and unchanged. -array<T>means an array whose elements are of typeT. - The syntax is currently invalid in PHP and therefore does not introduce a backward compatibility break. **Example**class UserService { public function getAllUsers(): array<User> { return [new User("Alice"), new User("Bob")]; } public function saveRoles(User $user, array<Role> $roles): void { // Some database call } public function streamAllUsers(): Generator<User> { yield new User("Alice"); yield new User("Bob"); } public function iterateAllUsers(): ArrayIterator<User> { return new ArrayIterator([new User("Alice"), new User("Bob")]); } public function getUserProvider(): Traversable<User> { return new ArrayIterator([new User("Alice"), new User("Bob")]); } public function normalizeNames(iterable<string> $names): iterable<string> { foreach ($names as $name) { yield trim($name); } } }**Runtime semantics and enforcement** The goal is thatarray<T>and related iterable parameterizations behave like other PHP types: if a value is passed or returned that violates the declared type, aTypeErroris 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 againstT. 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 violatesT, throwTypeErrorat the point of iteration. This mirrors the fact thatiterablemay 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 explorearray<TKey, TValue>andGenerator<TKey, TValue>. **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 shorthandT[]should be part of the initial scope or a follow up - Whether supportingTKeyshould 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.