Howdy Stephen,
It seems like everyone always gets really hung up on generics! That or how to syntactically implement this.
Hi
Given other improvements in the language, I don't really see much need for the ability to specify fixed keys and their types (ie associative arrays) (I assume that's what the "['a' => string]" syntax is meant to be?)
Is there some fundamental aspect of the original arrayof RFC that prevents it from being revived today? The whole "does it include nulls" part is moot now presumably because we have both ? And |null, and the Type[] syntax is very common in docblocks.
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
This comparison, while not a perfect match, is a great source of learning and inspiration.
While it’s true that PHP can take arrays and mash them into objects, I have to ask myself if this other language has this
feature, why don't we? Is it because we don’t care? Is it a bad feature? I don't think so.
I have a PR for WebSockets that integrates with Apache. Why hasn’t it been done before?
I don’t think this is an oversight on others, but rather, the community is what makes PHP better, challenging norms.
I’m not saying it will outperform what objectiveness currently provides, but I'm also not saying it won’t! I don’t think there’s a negative to
me implementing this syntax, and who knows, maybe it will be awesome for performance. I think what we should consider is that other
languages have this, and I feel the community wants this but is hung up on generics, which may have been an oversight.? I’m pretty new
here, and I’d love to make a meaningful impact, so the fact that this idea has been brought up before is encouraging.
Take, for example:
interface iArrayA ['a' => string, 'b' => string, 'c' => ?string, ‘d’ => SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$a = new Dict<string, iArrayA>;
Maybe the signature for Dict is:
class Dict<R is string | int, S is mixed> {}
Everyone harps on Generics, but no one can say how I'm supposed to model iArrayA if we focus on Generics.
We cannot safely define this now, as iArrayA is not a valid interface. I believe that is what I'm advocating for alone.
Array interfaces.
Best,
Richard Miles
Howdy Stephen,
It seems like everyone always gets really hung up on generics! That or how to syntactically implement this.
Hi
Given other improvements in the language, I don't really see much need for the ability to specify fixed keys and their types (ie associative arrays) (I assume that's what the "['a' => string]" syntax is meant to be?)
Is there some fundamental aspect of the original arrayof RFC that prevents it from being revived today? The whole "does it include nulls" part is moot now presumably because we have both ? And |null, and the Type[] syntax is very common in docblocks.
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
This comparison, while not a perfect match, is a great source of learning and inspiration.While it’s true that PHP can take arrays and mash them into objects, I have to ask myself if this other language has this
feature, why don't we? Is it because we don’t care? Is it a bad feature? I don't think so.
I have a PR for WebSockets that integrates with Apache. Why hasn’t it been done before?
I don’t think this is an oversight on others, but rather, the community is what makes PHP better, challenging norms.I’m not saying it will outperform what objectiveness currently provides, but I'm also not saying it won’t! I don’t think there’s a negative to
me implementing this syntax, and who knows, maybe it will be awesome for performance. I think what we should consider is that other
languages have this, and I feel the community wants this but is hung up on generics, which may have been an oversight.? I’m pretty new
here, and I’d love to make a meaningful impact, so the fact that this idea has been brought up before is encouraging.Take, for example:
interface iArrayA ['a' => string, 'b' => string, 'c' => ?string, ‘d’ => SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$a = new Dict<string, iArrayA>;
Maybe the signature for Dict is:
class Dict<R is string | int, S is mixed> {}
Everyone harps on Generics, but no one can say how I'm supposed to model iArrayA if we focus on Generics.
We cannot safely define this now, as iArrayA is not a valid interface. I believe that is what I'm advocating for alone.
Array interfaces.Best,
Richard Miles
Hi Richard,
To be clear I'm not really suggesting "mash arrays into objects". I'm saying that with the advent of constructor property promotion, property types, readonly properties, property hooks, etc, there's much less reason (and IMO much less developer desire) to use a "hash" (associative array) in PHP in the first place. Classes (and the instances of them) with typed properties seem like a much more common solution to that problem, in my view. That they can be created from an associative array using argument unpacking (aka the splat operator) is a side benefit that facilitates working with legacy code (which is often full of associative arrays) IMO.
What a class with properties and all the modern niceties can't (ergonomically) do, is provide a list of objects of a given type - which is exactly what the arrayof
(aka Type[]) syntax would give us.
Cheers
Stephen
Howdy Stephen,
It seems like everyone always gets really hung up on generics! That or how to syntactically implement this.
Hi
Given other improvements in the language, I don't really see much need for the ability to specify fixed keys and their types (ie associative arrays) (I assume that's what the "['a' => string]" syntax is meant to be?)
Is there some fundamental aspect of the original arrayof RFC that prevents it from being revived today? The whole "does it include nulls" part is moot now presumably because we have both ? And |null, and the Type[] syntax is very common in docblocks.
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
This comparison, while not a perfect match, is a great source of learning and inspiration.While it’s true that PHP can take arrays and mash them into objects, I have to ask myself if this other language has this
feature, why don't we? Is it because we don’t care? Is it a bad feature? I don't think so.
I have a PR for WebSockets that integrates with Apache. Why hasn’t it been done before?
I don’t think this is an oversight on others, but rather, the community is what makes PHP better, challenging norms.I’m not saying it will outperform what objectiveness currently provides, but I'm also not saying it won’t! I don’t think there’s a negative to
me implementing this syntax, and who knows, maybe it will be awesome for performance. I think what we should consider is that other
languages have this, and I feel the community wants this but is hung up on generics, which may have been an oversight.? I’m pretty new
here, and I’d love to make a meaningful impact, so the fact that this idea has been brought up before is encouraging.Take, for example:
interface iArrayA ['a' => string, 'b' => string, 'c' => ?string, ‘d’ => SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$a = new Dict<string, iArrayA>;
Maybe the signature for Dict is:
class Dict<R is string | int, S is mixed> {}
Everyone harps on Generics, but no one can say how I'm supposed to model iArrayA if we focus on Generics.
We cannot safely define this now, as iArrayA is not a valid interface. I believe that is what I'm advocating for alone.
Array interfaces.Best,
Richard Miles
Hello,
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
I feel like Typescript is the wrong model to follow. The type system in Typescript is Turing Complete (https://github.com/microsoft/TypeScript/issues/14833) and php barely has a type system. It doesn’t even have consistent type checking, for that matter (properties are checked differently than arguments which are checked differently than constructor arguments — and the fact they agree with each other at all, is interesting, because they don’t arrive at the same conclusions in the same way. I’ve been dealing with subtle bugs here for weeks on an unannounced RFC implementation) and this is why generics is a can of worms: implementing it would essentially force a rewrite of the type system into a proper type system.
In my honest opinion, before we can even have this type of conversation, we need to have an RFC about the syntax (there may already be one, I haven’t checked — and internet is spotty where I currently am). The pattern matching RFC was proposed as though it would be written one way, people have thrown out ideas of different syntax, but I don’t think there is an “official” syntax. A good starting point may be to simply propose an RFC about syntax so future RFCs can be consistent.
— Rob
Howdy Rob,
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
I feel like Typescript is the wrong model to follow. The type system in Typescript is Turing Complete (https://github.com/microsoft/TypeScript/issues/14833) and php barely has a type system. It doesn’t even have consistent type checking, for that matter (properties are checked differently than arguments which are checked differently than constructor arguments — and the fact they agree with each other at all, is interesting, because they don’t arrive at the same conclusions in the same way. I’ve been dealing with subtle bugs here for weeks on an unannounced RFC implementation) and this is why generics is a can of worms: implementing it would essentially force a rewrite of the type system into a proper type system.
In my honest opinion, before we can even have this type of conversation, we need to have an RFC about the syntax (there may already be one, I haven’t checked — and internet is spotty where I currently am). The pattern matching RFC was proposed as though it would be written one way, people have thrown out ideas of different syntax, but I don’t think there is an “official” syntax. A good starting point may be to simply propose an RFC about syntax so future RFCs can be consistent.
— Rob
I actually did not know it was turning complete, very interesting! While it is easy for anyone to say, ‘we're not even close to typescript,’
that’s precisely what brings me to the table. I would be happy with us just voting on syntax. It seems like past RFC’s only
ever got hung up on generics (wrongfully?). I want to work on implementing generics, too, after this. I feel this is probably a good
stepping stone.
A vote would solidify the following:
interface iArrayA ['a' => string ]
interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’ => SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ];
That would allow us to move into an implementation discussion, which is also absolutely needed.
Best,
Richard Miles
Howdy Rob,
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
I feel like Typescript is the wrong model to follow. The type system in Typescript is Turing Complete (https://github.com/microsoft/TypeScript/issues/14833) and php barely has a type system. It doesn’t even have consistent type checking, for that matter (properties are checked differently than arguments which are checked differently than constructor arguments — and the fact they agree with each other at all, is interesting, because they don’t arrive at the same conclusions in the same way. I’ve been dealing with subtle bugs here for weeks on an unannounced RFC implementation) and this is why generics is a can of worms: implementing it would essentially force a rewrite of the type system into a proper type system.
In my honest opinion, before we can even have this type of conversation, we need to have an RFC about the syntax (there may already be one, I haven’t checked — and internet is spotty where I currently am). The pattern matching RFC was proposed as though it would be written one way, people have thrown out ideas of different syntax, but I don’t think there is an “official” syntax. A good starting point may be to simply propose an RFC about syntax so future RFCs can be consistent.
— Rob
I actually did not know it was turning complete, very interesting!
While it is easy for anyone to say, ‘we're not even close to
typescript,’
that’s precisely what brings me to the table. I would be happy with us
just voting on syntax. It seems like past RFC’s only
ever got hung up on generics (wrongfully?). I want to work on
implementing generics, too, after this. I feel this is probably a good
stepping stone.A vote would solidify the following:
interface iArrayA ['a' => string ]
interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’
=> SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ];That would allow us to move into an implementation discussion, which is
also absolutely needed.Best,
Richard Miles
As Stephen already said, we have this already. It's spelled like this:
class A {
public function __construct(public string $a) {}
}
class B extends A {
public function __construct(
public string $a,
public string $b,
public ?string $c,
public SomeClass $d,
public A $e,
mixed $f,
) {}
}
If you know the keys at code time, use a class, not an array. Full stop, period, end of story. Using an array as a record object in PHP >= 7 is wrong. It's slower, more memory-intensive, less ergonomic, harder to debug, harder to statically analyze, harder to learn, harder to use. If you're still doing that, it's past time to stop. If your legacy application from the PHP 3 days is still doing that, it's past time to upgrade it.
So new language features to make "misuse arrays as objects" easier are actively counter-productive.
A Dict / Hashmap is appropriate when you do not know the keys in advance, and thus cannot use a pre-defined object for it. There are plenty of use cases for that, but in that case, all you need type-wise is the key type and value type, because all entries should be of the same type (give or take inheritance). Mixing in random other types... is wrong. That's the whole reason why people keep talking about collections/typed arrays/generics.
So the "array interface" syntax you keep posting is actively counter-productive.
--Larry Garfield
Hey Larry,
interface iArrayA ['a' => string ]
interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’
=> SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ];
I will start by advocating for how much cleaner this is from its objective counterpart. It also aids in reusability.
As Stephen already said, we have this already. It's spelled like this:
class A {
public function __construct(public string $a) {}
}class B extends A {
public function __construct(
public string $a,
public string $b,
public ?string $c,
public SomeClass $d,
public A $e,
mixed $f,
) {}
}If you know the keys at code time, use a class, not an array. Full stop, period, end of story. Using an array as a record object in PHP >= 7 is wrong. It's slower, more memory-intensive, less ergonomic, harder to debug, harder to statically analyze, harder to learn, harder to use. If you're still doing that, it's past time to stop. If your legacy application from the PHP 3 days is still doing that, it's past time to upgrade it.
I feel this is a common misconception, or can you clarify this for me?
Array access is faster than object access.
I didn’t want to claim this without first running the benchmarks:
https://github.com/EFTEC/php-benchmarks/blob/master/benchmark_array_vs_object.php
php-benchmarks/benchmark_array_vs_object.php at master · EFTEC/php-benchmarks
github.com
Good news is these benchmarks already exist! I just cloned this repo, required the table builder, and profit.
composer require eftec/mapache-commons
php benchmark_array_vs_object.php
...
To save you the trouble you can refer to this Medium post:
https://medium.com/cook-php/php-benchmark-time-fc19d813aa98
PHP, Benchmark time
medium.com
I figured you’d say something about the ’newest’ syntax so I added
class DummyClass
{
public function __construct(public $hello, public $second, public $third)
{
}
}
Thus, my results are as follows:
Array numeric no factory: 0% baseline at 0.414 (mind you im on an older MacBook)
Array no factory 0.95%
Array numeric factory: 566.1%
Array factory: 650.07%
Object Constructor: 609.03%
Object no constructor 82.77%
Object no constructor setter/getter: 2058.43%
Object no constructor magic methods: 2273.91%
Object no constructor stdClass: 112.53%
These were pretty consistent with the medium post.
So new language features to make "misuse arrays as objects" easier are actively counter-productive.
A Dict / Hashmap is appropriate when you do not know the keys in advance, and thus cannot use a pre-defined object for it. There are plenty of use cases for that, but in that case, all you need type-wise is the key type and value type, because all entries should be of the same type (give or take inheritance). Mixing in random other types... is wrong. That's the whole reason why people keep talking about collections/typed arrays/generics.
I think the point we can take away from this is that we could
speed arrays up even more if we make typed arrays stricly bound and not a ‘hash’.
If we knew the keys in advance then in theroy we could make access based on the
numeric value of that property in the interface definition.
But as I keep saying this is worth investigating.
So the "array interface" syntax you keep posting is actively counter-productive.
I’m absolutely just trying to help while I have an abundance of free time. I do admit to been
a n00b sometimes. If something isn’t fast lets talk about how we might make it faster.
I don’t think anyone disagrees with you in that this is a big undertaking that shouldn’t be
taken lightly, but the community is strong and we’ll manage, even if at a turtles pace :)
If my understanding above is correct then Larry’s message actually highlights why we
should implement this feature. The community thinks objects are the way to go,
since its the only way to go.
Best,
Richard Miles
Howdy people,
Hey Larry,
interface iArrayA ['a' => string ]
interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’
=> SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ];I will start by advocating for how much cleaner this is from its objective counterpart. It also aids in reusability.
As Stephen already said, we have this already. It's spelled like this:
class A {
public function __construct(public string $a) {}
}class B extends A {
public function __construct(
public string $a,
public string $b,
public ?string $c,
public SomeClass $d,
public A $e,
mixed $f,
) {}
}If you know the keys at code time, use a class, not an array. Full stop, period, end of story. Using an array as a record object in PHP >= 7 is wrong. It's slower, more memory-intensive, less ergonomic, harder to debug, harder to statically analyze, harder to learn, harder to use. If you're still doing that, it's past time to stop. If your legacy application from the PHP 3 days is still doing that, it's past time to upgrade it.
I feel this is a common misconception, or can you clarify this for me?
Array access is faster than object access.
I didn’t want to claim this without first running the benchmarks:https://github.com/EFTEC/php-benchmarks/blob/master/benchmark_array_vs_object.php
Good news is these benchmarks already exist! I just cloned this repo, required the table builder, and profit.composer require eftec/mapache-commons
php benchmark_array_vs_object.php
...
To save you the trouble you can refer to this Medium post:
https://medium.com/cook-php/php-benchmark-time-fc19d813aa98I figured you’d say something about the ’newest’ syntax so I added
class DummyClass
{
public function __construct(public $hello, public $second, public $third)
{
}
}
Thus, my results are as follows:Array numeric no factory: 0% baseline at 0.414 (mind you im on an older MacBook)
Array no factory 0.95%
Array numeric factory: 566.1%
Array factory: 650.07%
Object Constructor: 609.03%
Object no constructor 82.77%
Object no constructor setter/getter: 2058.43%
Object no constructor magic methods: 2273.91%
Object no constructor stdClass: 112.53%These were pretty consistent with the medium post.
So new language features to make "misuse arrays as objects" easier are actively counter-productive.
A Dict / Hashmap is appropriate when you do not know the keys in advance, and thus cannot use a pre-defined object for it. There are plenty of use cases for that, but in that case, all you need type-wise is the key type and value type, because all entries should be of the same type (give or take inheritance). Mixing in random other types... is wrong. That's the whole reason why people keep talking about collections/typed arrays/generics.
I think the point we can take away from this is that we could
speed arrays up even more if we make typed arrays stricly bound and not a ‘hash’.
If we knew the keys in advance then in theroy we could make access based on the
numeric value of that property in the interface definition.
But as I keep saying this is worth investigating.So the "array interface" syntax you keep posting is actively counter-productive.
I’m absolutely just trying to help while I have an abundance of free time. I do admit to been
a n00b sometimes. If something isn’t fast lets talk about how we might make it faster.
I don’t think anyone disagrees with you in that this is a big undertaking that shouldn’t be
taken lightly, but the community is strong and we’ll manage, even if at a turtles pace :)If my understanding above is correct then Larry’s message actually highlights why we
should implement this feature. The community thinks objects are the way to go,
since its the only way to go.Best,
Richard Miles
So since im not getting any feedback about the above, we can concrete the fastness of array over objects access.
I’m ready to make this Syntax Proposal RFC but still need RFC karma.
Could someone please give my wiki.php.net http://wiki.php.net/ account access: wookieetyler
Best,
Richard Miles
Howdy Rob,
I appreciate your feedback, and I think it’s valid. I try to compare my expectations to what is possible in typescript.
I feel like Typescript is the wrong model to follow. The type system in Typescript is Turing Complete (https://github.com/microsoft/TypeScript/issues/14833) and php barely has a type system. It doesn’t even have consistent type checking, for that matter (properties are checked differently than arguments which are checked differently than constructor arguments — and the fact they agree with each other at all, is interesting, because they don’t arrive at the same conclusions in the same way. I’ve been dealing with subtle bugs here for weeks on an unannounced RFC implementation) and this is why generics is a can of worms: implementing it would essentially force a rewrite of the type system into a proper type system.
In my honest opinion, before we can even have this type of conversation, we need to have an RFC about the syntax (there may already be one, I haven’t checked — and internet is spotty where I currently am). The pattern matching RFC was proposed as though it would be written one way, people have thrown out ideas of different syntax, but I don’t think there is an “official” syntax. A good starting point may be to simply propose an RFC about syntax so future RFCs can be consistent.
— Rob
I actually did not know it was turning complete, very interesting!
While it is easy for anyone to say, ‘we're not even close to
typescript,’
that’s precisely what brings me to the table. I would be happy with us
just voting on syntax. It seems like past RFC’s only
ever got hung up on generics (wrongfully?). I want to work on
implementing generics, too, after this. I feel this is probably a good
stepping stone.A vote would solidify the following:
interface iArrayA ['a' => string ]
interface iArrayB extends iArrayA ['b' => string, 'c' => ?string, ‘d’
=> SomeClass, ‘e’=> iArrayA, ‘f’ => mixed ]
$array = (iArrayA &| iArrayB) [ ‘a’ => ‘hello’ ];That would allow us to move into an implementation discussion, which is
also absolutely needed.Best,
Richard MilesAs Stephen already said, we have this already. It's spelled like this:
class A {
public function __construct(public string $a) {}
}class B extends A {
public function __construct(
public string $a,
public string $b,
public ?string $c,
public SomeClass $d,
public A $e,
mixed $f,
) {}
}If you know the keys at code time, use a class, not an array. Full stop, period, end of story. Using an array as a record object in PHP >= 7 is wrong. It's slower, more memory-intensive, less ergonomic, harder to debug, harder to statically analyze, harder to learn, harder to use. If you're still doing that, it's past time to stop. If your legacy application from the PHP 3 days is still doing that, it's past time to upgrade it.
So new language features to make "misuse arrays as objects" easier are actively counter-productive.
A Dict / Hashmap is appropriate when you do not know the keys in advance, and thus cannot use a pre-defined object for it. There are plenty of use cases for that, but in that case, all you need type-wise is the key type and value type, because all entries should be of the same type (give or take inheritance). Mixing in random other types... is wrong. That's the whole reason why people keep talking about collections/typed arrays/generics.
So the "array interface" syntax you keep posting is actively counter-productive.
--Larry Garfield
No offense, but this whole reply seems pretty counter-productive. “Just use objects” might be a valid use-case for you, but that isn’t true for everyone.
There are a number of uses for arrays (values vs references, cow memory efficiency, spoed, flexibility, etc) over objects, not to mention all the legacy code out there that people won’t seem to pay to rewrite…
— Rob