On 01/11/2017 01:36, Andrea Faulds wrote:
Thank 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, or
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 would become a lot less of an issue if we had function overloading
in future *crosses fingers*.
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.
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").
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);`
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?
Would an "operator array" not solve this in the same manner that
__tostring does?
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) {
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++.
Thanks.
--
Mark Randall
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php