Re: RFC - Array Of for PHP 7
| From: | Andrea Faulds | Date: | Fri, 03 Nov 2017 02:27:02 +0000 |
| Subject: | Re: RFC - Array Of for PHP 7 | ||
| References: | 1 2 3 4 5 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-101036@lists.php.net to get a copy of this message | ||
Hi,
Mark Randall wrote:
On 01/11/2017 01:36, Andrea Faulds wrote:Yes, it is a bit unfortunate to deviate from the docs. But array<> is also a familiar syntax, yet it's unambiguous and wouldn't require the new complication of parentheses. For that reason I don't find [] a compelling option. Syntax æsthetics are nice but in the end it's readability that matters. orThank you for bringing this up. The introduction of nullables means that the type[] syntax is problematic and should probably be avoided now. As you say, there is an issue of ambiguity as to whether it would be interpreted as (?int)[] or ?(int[]).That would be a shame, TypeName[] is a defacto standard already for PHP docs (not to mention a absolute standard for many programming languages) and if it can be made to work it would be one less piece of syntax. IMHO ?(int[]) would be the way to go staying with the current trend,
alternatively bite the bullet and specific both like we do in docblocs: function fn(null | int[] $x) { ... } Generics gives the less ambiguous option: function fn(?array<int> $x) { ... }This makes things even more complicated.
This would become a lot less of an issue if we had function overloading in future *crosses fingers*.Why create an almost-array that works almost-everywhere when you can improve the actual array that works actually everywhere?Which brings up perhaps a longer term point, does the language need an inbuilt alternative to "array" that implements ArrayAccess and provides for an "Operator array" that will allow it to be cast to an native array just as __tostring does for objects that implement it. The benefit would be that type checking could be performed on initialization and assignment, and with "operator array" it would be transparent. The downside I see? Well, being a generic object it would not exhibit traditional PHP copy-on-write behaviour, unless that was somehow baked into the language as part of the class definition (in a similar manner to "abstract" or "implements CopyOnWrite").Our current infrastructure requires us to check every element of the array for conformance. While undesirable I believe this can be optimized away in the future if we care enough, and therefore not a show-stopper.
Your proposed objects would not be usable everywhere an array is, because they're not arrays, and by converting to an array you lose the type info, so we still have to iterate over the whole thing to type check. This would be significantly less useful than an actually typed array. I can see some benefit to it, but I'm not sure it's worth the effort.Something I've thought about but not gotten round to implementing is a typed array value. That is, you could write `$x = array<int>(1, 2, 3);Would an "operator array" not solve this in the same manner that __tostring does?and$x` would contain a typed array that would enforce the types of values added to it. This feels like a cleaner solution, but it introduces a new issue: does an array<int> type declaration require an array<int> value, or will it implicitly cast from vanilla array?
I think once we have operator overloading (and supported by native types) then we should be able to do the following: function fn(MyCollection<int> $y) { ... } generic class MyCollection<T1> { public function __construct(array $in) {A problem here is that we'd need to implement generics! That's quite the complex task. I do like the idea of generics, but I don't really expect them to get implemented (let alone accepted) any time soon. Maybe if I suddenly decide to take all my yearly paid holiday at once and am unusually determined. But there are much nicer things to go on holiday for…foreach ($in as $x) { if (!($x typeof T1)) { throw new InvalidArgumentException('...'); } }} } fn(['hello', 'world']); And the engine should be smart enough to create a new instance of MyCollection<int> with the defined constructor. I say overloading would be necessary as several different constructors may be required. Equally: generic class SomeArray<T1> { ... public function __operator_array(): array {return $this->privateInternalArray;} ... } function fn(array $x) { ... } fn(new SomeArray<int>(1, 2, 3));
Admittedly I do not know the PHP core with any degre of intimacy, but from a language perspective I can't think of a better way than generics, casting operators, and overloaded function constructors... ... and yes, that did include almost every major language wishlist item in a single go. Chalk it up to me romancing my long lost love of C++.We all have our wishlist features. :) I think I share some of yours. Thanks for your reply.
-- Andrea Faulds https://ajf.me/Thanks.-- Mark Randall