Hi!
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkey
I know this is a holiday season but it was extensively discussed and I
think most people already formed their opinions. I've put the voting
period as 3 weeks to have some time for people to vote even with the
holidays, etc.
The vote includes choice for the name. Vote for either name is counted
as the vote for the overall proposal, and 2/3 majority is required as
it's a language change.
Some more expanded summary of the arguments is here:
http://php100.wordpress.com/2014/12/14/objects-as-keys/ in case you're
interested.
Stas Malyshev
smalyshev@gmail.com
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkey
Am I right this only covers the transformation into the array. Once it's
in it's essential a array compatible key entity (string/integer) so when
you var_dump($array) you only get the values of a hash.
In other words: it would not be possible to actually get the object from
the key, just this string/integer which is supposed to reference it?
thanks,
- Markus
Hi Markus,
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkeyAm I right this only covers the transformation into the array. Once it's
in it's essential a array compatible key entity (string/integer) so when
you var_dump($array) you only get the values of a hash.In other words: it would not be possible to actually get the object from
the key, just this string/integer which is supposed to reference it?
Exactly. If I were to do this:
<?php
class Foo {
public $foo;
function __construct($foo) {
$this->foo = $foo;
}
function __toKey() {
return $this->foo;
}
}
$arr = [];
$arr[] = new Foo(1);
var_dump($arr);
I would get this:
array(1) {
[0]=>
int(1)
}
This is the main problem with the RFC: magic, implicit, one-way data loss (object to integer/string).
I was previously in favour of this, but it’d prevent actual indexing by objects in future, and I can’t think of any use cases which aren’t better solved by explicitly converting to a string/integer.
Thanks.
Andrea Faulds
http://ajf.me/
Exactly. If I were to do this:
<?php
class Foo {
public $foo;
function __construct($foo) {
$this->foo = $foo;
}
function __toKey() {
return $this->foo;
}
}
$arr = [];
$arr[] = new Foo(1);
var_dump($arr);I would get this:
array(1) {
[0]=>
int(1)
}
Er, a correction… the example should’ve been something like this:
$arr = [];
$arr[new Foo(1)] = NULL;
Producing this:
array(1) {
[1]=>
`NULL`
}
Obviously, it has no effect on values, only keys, sorry!
--
Andrea Faulds
http://ajf.me/
Hi,
All I can say is that the lack of this feature is one of the main reasons why Doctrine doesn't fully work with composite keys.
With this enhancement it would now become possible to implement a proper IdentityMap.
[]s,
Exactly. If I were to do this:
<?php
class Foo {
public $foo;
function __construct($foo) {
$this->foo = $foo;
}
function __toKey() {
return $this->foo;
}
}
$arr = [];
$arr[] = new Foo(1);
var_dump($arr);I would get this:
array(1) {
[0]=>
int(1)
}Er, a correction… the example should’ve been something like this:
$arr = [];
$arr[new Foo(1)] = NULL;Producing this:
array(1) {
[1]=>
NULL
}Obviously, it has no effect on values, only keys, sorry!
--
Andrea Faulds
http://ajf.me/
Hi Guilherme,
Hi,
All I can say is that the lack of this feature is one of the main reasons why Doctrine doesn't fully work with composite keys.
With this enhancement it would now become possible to implement a proper IdentityMap.
Are you sure you haven't misinterpreted the RFC?
Cheers
Matteo Beccati
Development & Consulting - http://www.beccati.com/
This is the main problem with the RFC: magic, implicit, one-way data
loss (object to integer/string).I was previously in favour of this, but it’d prevent actual indexing
by objects in future, and I can’t think of any use cases which aren’t
better solved by explicitly converting to a string/integer.
That's precisely the same reason why I voted Nay. And I wouldn't have
been able to put it down in words better than Andrea did.
Cheers
Matteo Beccati
Development & Consulting - http://www.beccati.com/
Am 16.12.2014 12:36 schrieb "Matteo Beccati" php@beccati.com:
I was previously in favour of this, but it’d prevent actual indexing
by objects in future, and I can’t think of any use cases which aren’t
better solved by explicitly converting to a string/integer.That's precisely the same reason why I voted Nay. And I wouldn't have
been able to put it down in words better than Andrea did.
That was my thought initially, too. But I think it is wrong. If PHP ever
gets around to provide objects-themselves-as-array-keys support, it can
easily do that
- only if the object does not have such a __toKey() method, or
- if the object has one, but it returns the object itself (which is
forbidden now by the RFC)
best regards
Patrick
Patrick Schaaf wrote on 16/12/2014 11:46:
Am 16.12.2014 12:36 schrieb "Matteo Beccati" php@beccati.com:
I was previously in favour of this, but it’d prevent actual indexing
by objects in future, and I can’t think of any use cases which aren’t
better solved by explicitly converting to a string/integer.
That's precisely the same reason why I voted Nay. And I wouldn't have
been able to put it down in words better than Andrea did.That was my thought initially, too. But I think it is wrong. If PHP ever
gets around to provide objects-themselves-as-array-keys support, it can
easily do that
- only if the object does not have such a __toKey() method, or
- if the object has one, but it returns the object itself (which is
forbidden now by the RFC)
Hm, that's an interesting thought. My thought had been that an
object-as-key would need to specify its hash anyway, so that two objects
of the same "value" would be automatically de-duped, just as two strings
are. But I guess an internally unique handle for the specific object
would also be a reasonable approach for some uses.
Perhaps like with Traversable, we could have a set of magic interfaces
(although I'm struggling to think of names for them, which may be a bad
sign):
a) an "abstract" base interface meaning "can be used as $bar in
$foo[$bar]"; like Traversable, this would not actually be implementable
directly, but be the parent of the following
b) an interface for objects which produce a one-way hash to use as the
key (as in the current proposal)
c) an interface for objects which can themselves be stored as the key,
with internally unique handle as identifier
d) an interface for objects which can themselves be stored as the key,
but with a custom "value" used as the identifier
This sounds complex, but wouldn't necessarily be. (c) is just a special
case of (d) with an implied default implementation of the value method.
And if the structure of the HashTable retained the index/key structure
we have now, but with the object pointer as an additional field, the
pseudo-code when an object was encountered in array-key context would be:
if $obj has interface (a) then
. if $obj has interface (c) then
. . key := get_internal_identifier($obj)
. . else key := $obj->getHash() // this covers (b) and (d)
. end
. store value against key
. if $obj has interface (c) or (d) then store additional pointer to
original object
else throw error
end
Importantly, the current proposal could be re-cast as an implementation
of interface (b) while neither promising nor ruling out (c) and/or (d).
--
Rowan Collins
[IMSoP]
Hi,
Le 16 déc. 2014 13:45, "Rowan Collins" rowan.collins@gmail.com a écrit :
Patrick Schaaf wrote on 16/12/2014 11:46:
Am 16.12.2014 12:36 schrieb "Matteo Beccati" php@beccati.com:
I was previously in favour of this, but it’d prevent actual indexing
by objects in future, and I can’t think of any use cases which aren’t
better solved by explicitly converting to a string/integer.That's precisely the same reason why I voted Nay. And I wouldn't have
been able to put it down in words better than Andrea did.
That was my thought initially, too. But I think it is wrong. If PHP ever
gets around to provide objects-themselves-as-array-keys support, it can
easily do that
- only if the object does not have such a __toKey() method, or
- if the object has one, but it returns the object itself (which is
forbidden now by the RFC)Hm, that's an interesting thought. My thought had been that an
object-as-key would need to specify its hash anyway, so that two objects of
the same "value" would be automatically de-duped, just as two strings are.
But I guess an internally unique handle for the specific object would also
be a reasonable approach for some uses.
Just a random thought: the __hash
method can just return spl_object_hash($this);
to have an object id.
--
Rowan Collins
[IMSoP]--
Cheers,
Florian Margaine
Hi!
I was previously in favour of this, but it’d prevent actual indexing
No, of course it won't - if we ever introduce indexing objects (which
probably will require rewrite of the HashTable, any takers?) it would be
very easy to index any object that does not implement __hash without any
BC problem, and convert all those implementing __hash to "return $this"
if desired.
by objects in future, and I can’t think of any use cases which
aren’t better solved by explicitly converting to a string/integer.
There's no implicit conversion, and explicit one is a) inacessible in
userspace for anything but string and b) annoying for the same reasons
for which __toString exists.
Stas Malyshev
smalyshev@gmail.com
Hi!
I was previously in favour of this, but it’d prevent actual indexing
No, of course it won't - if we ever introduce indexing objects (which
probably will require rewrite of the HashTable, any takers?) it would
be
very easy to index any object that does not implement __hash without
any
BC problem, and convert all those implementing __hash to "return $this"
if desired.by objects in future, and I can’t think of any use cases which
aren’t better solved by explicitly converting to a string/integer.There's no implicit conversion, and explicit one is a) inacessible in
userspace for anything but string and b) annoying for the same reasons
for which __toString exists.
Explicit conversion is trivial, just call whatever method you like. Sure, you can't write (int)$obj, but $obj->toInt() is just as expressive.
Hi!
Explicit conversion is trivial, just call whatever method you like.
Sure, you can't write (int)$obj, but $obj->toInt() is just as
expressive.
Exactly the same applies to __toString and whole ArrayAccess, yet we
still have them. Avoiding boilerplate code helps. Especially if
boilterplate code would look like:
if(is_object($foo)) {
$foo_key = $foo->toInt();
} else {
$foo_key = $foo;
}
$a[$foo] = 1;
Doing it each time is annoying.
Stas Malyshev
smalyshev@gmail.com
Hi!
Explicit conversion is trivial, just call whatever method you like.
Sure, you can't write (int)$obj, but $obj->toInt() is just as
expressive.Exactly the same applies to __toString and whole ArrayAccess, yet we
still have them. Avoiding boilerplate code helps. Especially if
boilterplate code would look like:if(is_object($foo)) {
$foo_key = $foo->toInt();
} else {
$foo_key = $foo;
}
$a[$foo] = 1;Doing it each time is annoying.
I was just confused by your statement that "explicit conversion is inacessible from userspace". But yeah, I guess with string keys you can just write $a[(string)$foo] and assume/hope it will do something meaningful whatever the type of $foo.
On Tue, Dec 16, 2014 at 9:39 AM, Matteo Beccati php@beccati.com
wrote:Hi Guilherme,Hi,
All I can say is that the lack of this feature is one of the main
reasons why Doctrine doesn't fully work with composite keys.
With this enhancement it would now become possible to implement a proper
IdentityMap.Are you sure you haven't misinterpreted the RFC?
Hi Matteo,
I did not. You may think I mentioned IdentityMap as entity map, but I'm
talking about entityPersister mapping or resultPointers consumptions that
happens inside Doctrine throughout the execution. Entity IdentityMap is
enough to use purely spl_object_hash()
. We should focus on the main goal
here, which is complex structures as keys.
As a very complex library developer I do see lots of use cases for this.
[]s,
On Tue, Dec 16, 2014 at 6:52 PM, Rowan Collins rowan.collins@gmail.com
wrote:
On 16 December 2014 18:50:06 GMT, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
Explicit conversion is trivial, just call whatever method you like.
Sure, you can't write (int)$obj, but $obj->toInt() is just as
expressive.Exactly the same applies to __toString and whole ArrayAccess, yet we
still have them. Avoiding boilerplate code helps. Especially if
boilterplate code would look like:if(is_object($foo)) {
$foo_key = $foo->toInt();
} else {
$foo_key = $foo;
}
$a[$foo] = 1;Doing it each time is annoying.
I was just confused by your statement that "explicit conversion is
inacessible from userspace". But yeah, I guess with string keys you can
just write $a[(string)$foo] and assume/hope it will do something meaningful
whatever the type of $foo.--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
guilhermeblanco@gmail.com wrote:
On Tue, Dec 16, 2014 at 9:39 AM, Matteo Beccati php@beccati.com
wrote:Are you sure you haven't misinterpreted the RFC?
I did not. You may think I mentioned IdentityMap as entity map, but I'm
talking about entityPersister mapping or resultPointers consumptions that
happens inside Doctrine throughout the execution. Entity IdentityMap is
enough to use purelyspl_object_hash()
. We should focus on the main goal
here, which is complex structures as keys.As a very complex library developer I do see lots of use cases for this.
AIUI, this RFC is meant to introduce some sugar only. Wouldn't it be
possible to have object hashes without __hash(), by introducing a
respective interface (maybe "Hashable" or "Identifiable") and requiring
the appropriate classes to implement this interface?
--
Christoph M. Becker
Hi!
AIUI, this RFC is meant to introduce some sugar only. Wouldn't it be
I'm not sure what you mean by "some sugar only". It introduces the
capability of using objects in array key context, which was not
available until now.
possible to have object hashes without __hash(), by introducing a
respective interface (maybe "Hashable" or "Identifiable") and requiring
the appropriate classes to implement this interface?
It's possible and essentially the same, replacing magic method (which is
how things were done in PHP since forever until now) with interface -
which probably would be slower to check, would still require dedicated
method name, probably starting with __, and will essentially do the same.
--
Stas Malyshev
smalyshev@gmail.com
Hi Stas,
Hi!
AIUI, this RFC is meant to introduce some sugar only. Wouldn't it be
I'm not sure what you mean by "some sugar only". It introduces the
capability of using objects in array key context, which was not
available until now.
That’s not true: the RFC doesn’t allow objects to be keys, it just adds implicit conversion. This is just sugar for an explicit conversion to int or string.
--
Andrea Faulds
http://ajf.me/
Hi!
On 17 Dec 2014, at 01:32, Stanislav Malyshev smalyshev@gmail.com
wrote:Hi!
AIUI, this RFC is meant to introduce some sugar only. Wouldn't
it beI'm not sure what you mean by "some sugar only". It introduces the
capability of using objects in array key context, which was not
available until now.That’s not true: the RFC doesn’t allow objects to be keys,
And reading what I actually wrote would reveal that I did not write
"allow objects to be keys", I wrote "using objects in array key
context", and this is of course true. Please do read what you calling
"not true" before doing it. I explained it numerous times, I even wrote
a special blog post explaining it, I referenced it here, but it as if
nobody is actually reading anything before repeating the same arguments.
it just adds implicit conversion. This is just sugar for an explicit
conversion to int or string.
And this is completely false. While the result of the function must be
int or string, saying any function that returns int or string is "just
sugar for an explicit conversion to int or string" is false. This
function has its separate purpose which does not equal converting to any
specific type, but is suited for its unique context. You can have it
return the same result as (int) or (string) but you don't have to.
Stas Malyshev
smalyshev@gmail.com
Stanislav Malyshev wrote:
AIUI, this RFC is meant to introduce some sugar only. Wouldn't it be
I'm not sure what you mean by "some sugar only". It introduces the
capability of using objects in array key context, which was not
available until now.
Yes, but it is already possible to call an object's method in array key
context, so in combination with an appropriate interface the same can be
accomplished.
possible to have object hashes without __hash(), by introducing a
respective interface (maybe "Hashable" or "Identifiable") and requiring
the appropriate classes to implement this interface?It's possible and essentially the same, replacing magic method (which is
how things were done in PHP since forever until now) with interface -
which probably would be slower to check, would still require dedicated
method name, probably starting with __, and will essentially do the same.
I didn't mean to argue against the RFC, but merely wanted to point out
that one could have object hashes without the proposed magic method
(albeit in a more contrived way).
Frankly, I don't understand Guilherme's claim:
| With this enhancement it would now become possible to implement a
| proper IdentityMap.
It seems to me that is already possible since PHP 5.0.0. I may be
missing an important detail, though.
BTW: as a userland developer I would not have called the dedicated
method __X, because __* is reserved for PHP's internal usage, AIUI.
--
Christoph M. Becker
Hi!
Yes, but it is already possible to call an object's method in array key
context, so in combination with an appropriate interface the same can be
accomplished.
No, it's not possible. It is possible to call object method in an
expression, and then use the result of the expression as an array key.
But to do that you'd have to check that you're dealing with the object
and the call the special method.
Looks like you don't understand why PHP has magic methods - since your
argument applies to every one of them. Why have __toString if you can
just call object method? Why have __call if you could just check if
method exists and call a special method if it doesn't? Why have __isset
if you could just call special method on an object and pass it the
property name? Of course, it's "just sugar". All programming languages
are "just sugar" by that definition.
I didn't mean to argue against the RFC, but merely wanted to point out
that one could have object hashes without the proposed magic method
(albeit in a more contrived way).
You could have everything in a more contrived way. PHP 2 was Turing
complete, I am sure. Were we just wasting time these last 15 or so years
because everything was done in PHP since then was already possible,
albeit "in a more contrived way"? Or maybe there's some value in making
the ways significantly less contrived? IMO, that's the whole point of
what we're doing here.
Stas Malyshev
smalyshev@gmail.com
Stanislav Malyshev wrote on 17/12/2014 02:14:
No, it's not possible. It is possible to call object method in an
expression, and then use the result of the expression as an array key.
But to do that you'd have to check that you're dealing with the object
and the call the special method.
I think what Christoph was getting at is that you could implement an
object map pretty simply by requiring the objects being added to
implement a particular interface, as in:
...
function add ( Hashable $obj ) {
$this->data[ $obj->getHash() ] = $obj;
}
...
The main thing that the current RFC would simplify is being able to
accept a mixture of objects and scalars without performing an extra
check; currently, you'd have to write something like this:
...
function add ( $scalar_or_obj ) {
if ( is_scalar($scalar_or_obj) ) {
$this->data[ $scalar_or_obj ] = $scalar_or_obj;
} elseif ( $scalar_or_obj instanceOf Hashable ) {
$this->data[ $obj->getHash() ] = $obj;
} else {
throw new InvalidArgumentException;
}
}
...
Which is certainly uglier, any maybe was the case that Guilherme had in
mind, but it's not like you have to build a whole new type of data
structure, just add a few lines of implementation.
Compare that to trying to store the actual objects as keys, which would
require a lot more than a few lines of code to emulate in pure PHP.
Luckily, we have SplObjectStorage, which maybe makes that rather less
urgent as well.
Regards,
Rowan Collins
[IMSoP]
Rowan Collins wrote:
Stanislav Malyshev wrote on 17/12/2014 02:14:
No, it's not possible. It is possible to call object method in an
expression, and then use the result of the expression as an array key.
But to do that you'd have to check that you're dealing with the object
and the call the special method.I think what Christoph was getting at is that you could implement an
object map pretty simply by requiring the objects being added to
implement a particular interface, as in:....
function add ( Hashable $obj ) {
$this->data[ $obj->getHash() ] = $obj;
}
....The main thing that the current RFC would simplify is being able to
accept a mixture of objects and scalars without performing an extra
check; currently, you'd have to write something like this:....
function add ( $scalar_or_obj ) {
if ( is_scalar($scalar_or_obj) ) {
$this->data[ $scalar_or_obj ] = $scalar_or_obj;
} elseif ( $scalar_or_obj instanceOf Hashable ) {
$this->data[ $obj->getHash() ] = $obj;
} else {
throw new InvalidArgumentException;
}
}
....Which is certainly uglier, any maybe was the case that Guilherme had in
mind, but it's not like you have to build a whole new type of data
structure, just add a few lines of implementation.
Yes, that is what I was trying to convey. :)
Compare that to trying to store the actual objects as keys, which would
require a lot more than a few lines of code to emulate in pure PHP.
Luckily, we have SplObjectStorage, which maybe makes that rather less
urgent as well.
I agree. However, the RFC mentions a related open issue[1]:
| Should SplObjectStorage support calling __hash for an object if it
| exists?
It might be good to discuss and resolve this issue, as Derick has
already pointed out[2].
[1] https://wiki.php.net/rfc/objkey#open_issues
[2] http://marc.info/?l=php-internals&m=141881792424772&w=2
--
Christoph M. Becker
Hi!
Luckily, we have SplObjectStorage, which maybe makes that rather less
urgent as well.
SplObjectStorage doesn't do this - SplObjectStorage uses objects'
identity, which means two GMP(1)'s are different objects.
--
Stas Malyshev
smalyshev@gmail.com
Luckily, we have SplObjectStorage, which maybe makes that rather less
urgent as well.
SplObjectStorage doesn't do this - SplObjectStorage uses objects'
identity, which means two GMP(1)'s are different objects.
Silly question time again ...
What 'precisely' is the problem that 'Objects as keys' is trying to
solve? I think what I am asking is just how should a 'modern' design
using OO actually build a multidimentional array of objects?
What I am currently doing is building a conventional array of which one
element is the attached object. Other elements of the array include the
primary key and other data useful for sorting the order along with
identifying cross links to other objects. I can get to the underlying
object just by looking up the primary key in the array.
Where does SplObjectStorage fit into this, and more important how does
creating a new object fit in with adding it as a key in an array. I need
the handle to the object and I ideally I need to know what is in the
object so I seem to be missing something.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Lester Caine wrote:
Luckily, we have SplObjectStorage, which maybe makes that rather less
urgent as well.
SplObjectStorage doesn't do this - SplObjectStorage uses objects'
identity, which means two GMP(1)'s are different objects.Silly question time again ...
What 'precisely' is the problem that 'Objects as keys' is trying to
solve?
Stas explained that in a blog post:
http://php100.wordpress.com/2014/12/14/objects-as-keys/.
I think what I am asking is just how should a 'modern' design
using OO actually build a multidimentional array of objects?What I am currently doing is building a conventional array of which one
element is the attached object. Other elements of the array include the
primary key and other data useful for sorting the order along with
identifying cross links to other objects. I can get to the underlying
object just by looking up the primary key in the array.Where does SplObjectStorage fit into this, and more important how does
creating a new object fit in with adding it as a key in an array. I need
the handle to the object and I ideally I need to know what is in the
object so I seem to be missing something.
IMHO that is better asked and discussed on php-general@lists.php.net.
--
Christoph M. Becker
Stanislav Malyshev wrote:
Yes, but it is already possible to call an object's method in array key
context, so in combination with an appropriate interface the same can be
accomplished.No, it's not possible. It is possible to call object method in an
expression, and then use the result of the expression as an array key.
But to do that you'd have to check that you're dealing with the object
and the call the special method.
Sorry for expressing myself imprecisely. Thanks to Rowan this is
hopefully clarified now, see
http://marc.info/?l=php-internals&m=141882255826352&w=2.
Looks like you don't understand why PHP has magic methods - since your
argument applies to every one of them. Why have __toString if you can
just call object method? Why have __call if you could just check if
method exists and call a special method if it doesn't? Why have __isset
if you could just call special method on an object and pass it the
property name? Of course, it's "just sugar". All programming languages
are "just sugar" by that definition.
I'm neither arguing against having magic methods and other (syntactic)
sugar in general, nor against having __hash() or __toKey() in
particular. It's perfectly fine for me, if the RFC passes.
I didn't mean to argue against the RFC, but merely wanted to point out
that one could have object hashes without the proposed magic method
(albeit in a more contrived way).You could have everything in a more contrived way. PHP 2 was Turing
complete, I am sure. Were we just wasting time these last 15 or so years
because everything was done in PHP since then was already possible,
albeit "in a more contrived way"? Or maybe there's some value in making
the ways significantly less contrived? IMO, that's the whole point of
what we're doing here.
I do really appreciate your work, and I enjoy having a more expressive
language. I justed wanted to point out Guilherme's apparent
misinterpretation of your RFC, see
http://marc.info/?l=php-internals&m=141882026225496&w=2.
--
Christoph M. Becker
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkey
I wonder why you opened voting on this, before resolving the "Open
Issues":
Open Issues
Should SplFixedArray support object indexes?
Should SplObjectStorage support calling __hash for an object if it exists?
cheers,
Derick
Hi,
Answering the question of Christopher Becker. It is not possible to
traverse and get your desired elements.
How would you achieve a foreach by key (returning object) without having to
store a separate list and track by hash or through an interface?
Cheers,
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkeyI wonder why you opened voting on this, before resolving the "Open
Issues":Open Issues
Should SplFixedArray support object indexes? Should SplObjectStorage support calling __hash for an object if it
exists?
cheers,
Derick--
--
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada
guilhermeblanco@gmail.com wrote:
Answering the question of Christopher Becker. It is not possible to
traverse and get your desired elements.
How would you achieve a foreach by key (returning object) without having to
store a separate list and track by hash or through an interface?
AIUI, the RFC proposes that __hash() returns a string or an int, and
this value (not the object itself) will be stored and retrieved as key
of the array.
https://wiki.php.net/rfc/objkey#proposal:
| Create a new magic method, __hash() which is called when object is
| supplied as a hash key, and returns string or integer that is used as
| the hash key.
--
Christoph M. Becker
On Wed Dec 17 2014 at 1:44:13 PM guilhermeblanco@gmail.com <
guilhermeblanco@gmail.com> wrote:
Hi,
Answering the question of Christopher Becker. It is not possible to
traverse and get your desired elements.
How would you achieve a foreach by key (returning object) without having to
store a separate list and track by hash or through an interface?
Which is one of the main problem with this very RFC.
What ends up being stored in the array is the hash, not the object. And
there is no immediate way of getting the key object back. The user writes:
$arr = array($obj => 2); but key($arr) returns the hash only.
As I said in the original discussion: this RFC is actually about having an
implicit call to __hash() whenever an object is used as an array key. You
can achieve exactly the same in userland with an explicit call.
I would rather wait (maybe indefinitely) to have a proper implementation of
objects as keys than have this compromise.
Best,
Hi!
As I said in the original discussion: this RFC is actually about having
an implicit call to __hash() whenever an object is used as an array key.
You can achieve exactly the same in userland with an explicit call.
It's like nobody have ever seen __toString before... Of course you can
do that 10-line boilerplate that Rowan outlined. The whole point of this
RFC is so you don't have to do the boilerplate.
I would rather wait (maybe indefinitely) to have a proper implementation
of objects as keys than have this compromise.
I have hard time to understand this - it's like somebody offering to
give you $100, with no conditions, and you say "no, I'd rather wait for
somebody giving me a billion dollars, until then I won't take the $100".
Having object as keys does not contradict this RFC in any way - though
the probability of it happening in PHP 7 is pretty much nil so you'd
have to wait at least several years, but most probably - forever. So you
pretty much choosing to have nothing over having something with no
upside at all. Why?
Stas Malyshev
smalyshev@gmail.com
This RFC proposes that we store the hash of an object instead of the
actual object. That's simply not useful to me and likely prevents us
from adding support for objects as keys in the future should we want
it.
In addition, it adds yet another behavior to arrays which do so many
things already. I would much rather have structures that focus on
narrow responsibilities and do that well, such as an improved Map
structure instead of SplObjectStorage. This isn't some pie-in-the-sky
wishing, either; I've been working on this for years now in my spare
time.
Hi!
This RFC proposes that we store the hash of an object instead of the
actual object. That's simply not useful to me
Fair enough, but this is not only about what is useful personally to you.
and likely prevents us
from adding support for objects as keys in the future should we want
No it does not. It was already explained several times. If it is ever
introduced, it can be used for objects that do not explicitly request
functionality in this RFC by enabling __hash() with no BC issues, since
this RFC only affects classes that explicitly ask for this specific
functionality. So if you, according to the above, would never use
__hash, absolutely nothing would prevent you from using objects as keys
if it ever happens (which it probably won't in the next 2-3 years).
In addition, it adds yet another behavior to arrays which do so many
things already. I would much rather have structures that focus on
It's exactly the same behavior, just available for select objects now.
Arrays don't do anything new, they still store key/value pairs, objects
do something new to enable you doing more things with value objects.
I would much rather have structures that focus on
narrow responsibilities and do that well, such as an improved Map
structure instead of SplObjectStorage
Nothing in this RFC prevents you from having such structures. In fact,
this RFC would enable more convenient handling of such structures,
providing common method for requesting the programmable hash value of
the object - a feature which most languages have, but PHP does not.
Stas Malyshev
smalyshev@gmail.com
and likely prevents us
from adding support for objects as keys in the future should we wantNo it does not. It was already explained several times. If it is ever
introduced, it can be used for objects that do not explicitly request
functionality in this RFC by enabling __hash() with no BC issues, since
this RFC only affects classes that explicitly ask for this specific
functionality. So if you, according to the above, would never use
__hash, absolutely nothing would prevent you from using objects as keys
if it ever happens (which it probably won't in the next 2-3 years).
Just because you say it doesn't affect it doesn't mean it doesn't. I
think it would be quite silly to support storing hashes and/or storing
objects and to me that blocks the latter since you are proposing the
former.
Nothing in this RFC prevents you from having such structures. In fact,
this RFC would enable more convenient handling of such structures,
providing common method for requesting the programmable hash value of
the object - a feature which most languages have, but PHP does not.
Programmable hashes of objects should be external to the object anyway
because eventually someone wants to store the same object in a
different way in two different structures.
Hi!
Just because you say it doesn't affect it doesn't mean it doesn't. I
think it would be quite silly to support storing hashes and/or storing
objects and to me that blocks the latter since you are proposing the
former.
I don't know why you think it's "quite silly" to have both scalar and
object keys, as that's exactly what would you need to implement with you
want object keys - scalar keys are not going to go anywhere. So your
assumption that this RFC somehow blocks objects as keys is still wrong.
Programmable hashes of objects should be external to the object anyway
because eventually someone wants to store the same object in a
different way in two different structures.
That is the requirement that no language I can think of implements -
Java, Python, Ruby, C# all have programmatic hash method, and none of
them changes it for different structures.
Stas Malyshev
smalyshev@gmail.com
Programmable hashes of objects should be external to the object anyway
because eventually someone wants to store the same object in a
different way in two different structures.That is the requirement that no language I can think of implements -
Java, Python, Ruby, C# all have programmatic hash method, and none of
them changes it for different structures.
C++ commonly does this. You pass a "hash function" as a template or
constructor argument and use that for the structure. Additionally,
this allows you to easily support types that don't natively provide
internal hashing functions (such as objects from a third party
library).
In this case, doing it like Java, C# et al is an example of most
languages getting it wrong, not them getting it right.
Hi!
As I said in the original discussion: this RFC is actually about having
an implicit call to __hash() whenever an object is used as an array key.
You can achieve exactly the same in userland with an explicit call.
It's like nobody have ever seen __toString before... Of course you can
do that 10-line boilerplate that Rowan outlined. The whole point of this
RFC is so you don't have to do the boilerplate.
Just to clarify, I in no way wanted to say that reducing that
boilerplate was not a good thing. I was responding to the concept that
this allows things which weren't previously possible. I definitely think
syntactic sugar can be a good thing, and can see the advantage of this
proposal.
I would rather wait (maybe indefinitely) to have a proper implementation
of objects as keys than have this compromise.
I have hard time to understand this - it's like somebody offering to
give you $100, with no conditions, and you say "no, I'd rather wait for
somebody giving me a billion dollars, until then I won't take the $100".
Having object as keys does not contradict this RFC in any way - though
the probability of it happening in PHP 7 is pretty much nil so you'd
have to wait at least several years, but most probably - forever. So you
pretty much choosing to have nothing over having something with no
upside at all. Why?
Yes, there are versions of objects-as-keys which are compatible with
this proposal; however, there are also versions which are not.
For instance, without this proposal we could implement something so that
for any object, $foo[$obj] = 42 stores the object as the key. If this
RFC is already in place, then any object which uses __hash (or whatever
name we give it) to return a scalar key cannot also be used in that way.
That may not be a big deal - the creator of the object can choose which
behaviour to use - but the creator of the containing structure couldn't,
which might be a nuisance.
I guess the other way in which it reduces the chance of a more
"complete" solution is a psychological one - once this is in there, the
number of cases that need object-as-key support will be even lower,
leaving those that aren't served by this version less likely to be
approached.
I'm on the fence on this one. For one thing, I think it might be
interesting to explore whether real objects as keys is actually as
difficult as some people are assuming. I can naively imagine a few ways
it could be implemented that seem in my mind to have minimal impact on
any array that doesn't use it, but haven't yet seen anyone seriously
discuss any possible approaches.
--
Rowan Collins
[IMSoP]
For one thing, I think it might be interesting to explore whether real
objects as keys is actually as difficult as some people are assuming.
I can naively imagine a few ways it could be implemented that seem in
my mind to have minimal impact on any array that doesn't use it, but
haven't yet seen anyone seriously discuss any possible approaches.
In fact, to expand on this, I'm going to stick my neck out and tell
everyone my crackpot theory, which someone who actually understands the
engine will probably demolish in 5 seconds flat, but makes sense in my
mind. :P
The implementation of arrays could remain the same, with a single
pointer to a second "shadow" HashTable, which would only be initialised
when an object was actually added as a key. Thus the memory overhead
would be reserving a single pointer per array (not per item), and the
execution overhead (for any existing array usage) would be a single
if(shadowPointer) check in a few key places.
The idea would be that the object would still be hashed - e.g. by
default with spl_object_hash, but with __hash if set - and that key
would be stored in the normal way. However, an extra entry would be
added to the shadow array, as though you had also called $shadow[
$obj->__hash() ] = $obj.
We might want to do something tricksy to the key, like adding a null
byte at the beginning, to make it less likely for a scalar key and an
object hash to collide. This would also allow further short-cutting in
lookups, since if the first byte was not \0, there would be no chance of
a match in the shadow array. (If it was \0, there might still not be a
shadow object, because null-prefixed strings are actually valid scalar
keys, but this seems unlikely to be a common occurrence.)
Whenever an array key is taken as input (e.g. $foo[$bar],
array_key_exists()
), the hash function would be called (much as in the
current RFC), and the corresponding value could be returned directly -
the shadow table would not need to be touched, so performance would be
identical to that of the current proposal.
A lookup in the shadow array would need to happen only when writing to
the array, and when a key was being given as output (e.g. foreach ( $a
as $k => $v ), array_search()
, key()
). This would happen at the speed of
normal random access, and scale with the number of objects used as keys,
not the number of items in the main array.
Like I say, I'm sure this is full of holes, and I'll leave it there
before I get too far down a dead end, but I thought it might be a more
productive line of thought than "this will probably never happen".
Regards,
--
Rowan Collins
[IMSoP]
Hi,
I originally considered you could retrieve the object key, but if it is not
possible by this RFC, I will switch my vote to no.
By storing hash one way it introduces a huge wtf to the language.
Cheers,
For one thing, I think it might be interesting to explore whether real
objects as keys is actually as difficult as some people are assuming. I can
naively imagine a few ways it could be implemented that seem in my mind to
have minimal impact on any array that doesn't use it, but haven't yet seen
anyone seriously discuss any possible approaches.In fact, to expand on this, I'm going to stick my neck out and tell
everyone my crackpot theory, which someone who actually understands the
engine will probably demolish in 5 seconds flat, but makes sense in my
mind. :PThe implementation of arrays could remain the same, with a single pointer
to a second "shadow" HashTable, which would only be initialised when an
object was actually added as a key. Thus the memory overhead would be
reserving a single pointer per array (not per item), and the execution
overhead (for any existing array usage) would be a single if(shadowPointer)
check in a few key places.The idea would be that the object would still be hashed - e.g. by default
with spl_object_hash, but with __hash if set - and that key would be stored
in the normal way. However, an extra entry would be added to the shadow
array, as though you had also called $shadow[ $obj->__hash() ] = $obj.We might want to do something tricksy to the key, like adding a null byte
at the beginning, to make it less likely for a scalar key and an object
hash to collide. This would also allow further short-cutting in lookups,
since if the first byte was not \0, there would be no chance of a match in
the shadow array. (If it was \0, there might still not be a shadow object,
because null-prefixed strings are actually valid scalar keys, but this
seems unlikely to be a common occurrence.)Whenever an array key is taken as input (e.g. $foo[$bar],
array_key_exists()
), the hash function would be called (much as in the
current RFC), and the corresponding value could be returned directly - the
shadow table would not need to be touched, so performance would be
identical to that of the current proposal.A lookup in the shadow array would need to happen only when writing to the
array, and when a key was being given as output (e.g. foreach ( $a as $k
=> $v ),array_search()
,key()
). This would happen at the speed of normal
random access, and scale with the number of objects used as keys, not the
number of items in the main array.Like I say, I'm sure this is full of holes, and I'll leave it there before
I get too far down a dead end, but I thought it might be a more productive
line of thought than "this will probably never happen".Regards,
--
Rowan Collins
[IMSoP]
guilhermeblanco@gmail.com wrote on 17/12/2014 12:43:
Answering the question of Christopher Becker. It is not possible to
traverse and get your desired elements.
How would you achieve a foreach by key (returning object) without having to
store a separate list and track by hash or through an interface?
SplObjectStorage supports that mechanism, although it's not the most
intuitive design. See this comment in the manual:
http://php.net/manual/en/class.splobjectstorage.php#114059
As others have pointed out, this proposal does not support that usage,
because the hash function is one-way, and you cannot get back the object
based only on the calculated key. All it does is reduce the boilerplate
needed for hashing an object to produce a suitable array key.
Hi!
I wonder why you opened voting on this, before resolving the "Open
Issues":Open Issues
Should SplFixedArray support object indexes? Should SplObjectStorage support calling __hash for an object if it exists?
These issues are not part of the RFC's target, they are possible
improvements to SPL if the RFC is accepted. I don't want to spend time
on them if it is not. If it is, then we can see how to improve SPL
classes to support it, but it's a different questions from the main RFC.
I just mentioned it in order to not forget these things need to be
discussed if the RFC is accepted.
--
Stas Malyshev
smalyshev@gmail.com
Hi!
I wonder why you opened voting on this, before resolving the "Open
Issues":Open Issues
Should SplFixedArray support object indexes? Should SplObjectStorage support calling __hash for an object if it exists?
These issues are not part of the RFC's target, they are possible
improvements to SPL if the RFC is accepted. I don't want to spend time
on them if it is not. If it is, then we can see how to improve SPL
classes to support it, but it's a different questions from the main RFC.
I just mentioned it in order to not forget these things need to be
discussed if the RFC is accepted.
That makes sense. They should probably have gone under "Future Scope"
rather than "Open Issues" in that case, looking at the wording on the
template, but not a big deal.
--
Rowan Collins
[IMSoP]
Hi!
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkeyI know this is a holiday season but it was extensively discussed and I
think most people already formed their opinions. I've put the voting
period as 3 weeks to have some time for people to vote even with the
holidays, etc.The vote includes choice for the name. Vote for either name is counted
as the vote for the overall proposal, and 2/3 majority is required as
it's a language change.Some more expanded summary of the arguments is here:
http://php100.wordpress.com/2014/12/14/objects-as-keys/ in case you're
interested.
I've not read the whole email thread, but I have read the RFC, sorry
if I missed something in the emails.
I've voted no, I really don't see any benefit to automatically calling
a magic method for a key, this is a kind of unintuitive magic for me.
For objects as keys to be useful (in my opinion), a foreach loop or
array_search must be able to return the object as the key component.
The RFC doesn't offer a way to retrieve the original object from the
stored hash, indeed without a refcount++ the object may not even exist
any more.
I honestly like the idea of "objects as keys", but this RFC doesn't offer that.
I'd like to initiate a vote on "objects as keys" RFC:
https://wiki.php.net/rfc/objkey
Hi,
After discussing this RFC with other members of AFUP, we would probably
be +1 on the idea of being able to really use objects as keys.
But, considering this RFC doesn't go all the way to "objects as keys"
(especially on the "using foreach doesn't get you the object back"
part), we ended up on the -1 side.
--
Pascal MARTIN, AFUP - French UG
http://php-internals.afup.org/