Skip to content

Conversation

@nikic
Copy link
Member

@nikic nikic commented Jan 8, 2021

Very much work in progress. A --disable-all build mostly works.

RFC: https://wiki.php.net/rfc/object_keys_in_arrays

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip
@nikic nikic added the RFC label Jan 8, 2021
Copy link
Contributor

@TysonAndre TysonAndre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be interesting to know what the overall performance impact is when this is finished.

I'm not really sure how I personally feel about this yet - it's convenient to have the array copy-on-write semantics for a mapping from an object to a value (unlike SplObjectStorage where you have to explicitly clone) as well as to guarantee that the object won't expire (previously using $array[spl_object_id($node)] = $value )
(and the engine optimizations for that)

  • e.g. ruby has symbols, python has a generic dict (but both have a separate list)

But this would be less certain that a key of a known array could be converted to a string (PHP type hints don't go beyond array), that a constant expression could be json encoded, etc.

  • e.g. false positives for foreach ($key as $val) { echo $key . ":" . json_encode($val); }

Would $obj->{$obj2} = $value work? What's the plan for edge cases like $$obj = $value/extract/$GLOBALS work?

  • objects as names for local/global variables doesn't have a good use case I can think of
  • it may complicate generating backtraces (or even representations of constant arrays, in general) if code had call_varargs(...[new stdClass() => true, Suit::Hearts => 7]); - json_encode would not be able to represent that, and may benefit from a JSON_SKIP_OBJECT_KEY|JSON_SKIP_NONSTRINGABLE_OBJECT_KEY flag

For unrelated reasons to this PR: Is it reasonable to assume that the pointer to a zend_object doesn't change (e.g. realloced) for the lifetime of an object (i.e. before it's garbage collected, even with reference count 1), are there exceptions to that rule?
(I've been assuming it is a safe assumption in an unrelated change I'm working on (e.g. zvals contain zend_object*, not a handle), but I'm not 100% certain. You'd be more familiar with that than me)

_val = _z;

#define ZEND_HASH_FOREACH_KEY_VAL(ht, _h, _key, _val) \
#define ZEND_HASH_FOREACH_ZKEY_VAL(ht, _key, _val) \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also adding macros for zend_long _h, zend_string *_key, zend_object *_obj might be easier from a migration standpoint for PECL code (the compiler could probably eliminate dead code if people backported that macro to php 8.0 and older)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ZKEY macros and functions are already intended to be polyfilled on older PHP versions. I've found that in most cases it's more convenient to keep the key as a zval rather than unpacking it, as most usages just pass through the key in some manner.

wip

wip

wip

wip

wip

wip

wip

wip

wip

wip
@nikic
Copy link
Member Author

nikic commented Jan 11, 2021

Would $obj->{$obj2} = $value work? What's the plan for edge cases like $$obj = $value/extract/$GLOBALS work?

No, that would convert $obj2 to string. Objects always have string keys. (Pedantic: Actually, objects can also have integer keys, and now object keys, but only via the ArrayObject loophole. This is not by-design.) Same for symbol tables.

For unrelated reasons to this PR: Is it reasonable to assume that the pointer to a zend_object doesn't change (e.g. realloced) for the lifetime of an object (i.e. before it's garbage collected, even with reference count 1), are there exceptions to that rule?

This is safe to assume :)

@dtakken
Copy link

dtakken commented Jan 11, 2021

Something that may be helpful here: I am considering to try and introduce a magic method __repr(), similar to __repr__ () in Python. It would have a default implementation returning a static unique string similar to:

"FooBar object at 0x56535154bd90"

This gives any object a default string representation. The distinction between __repr() and __toString() would also be the same as in Python. Classes can replace the default implementation and return any string. These custom string representations could be non-unique and dynamic.

Could this be helpful for cases like var_dump()?

@thomas-0816
Copy link

How does ksort() work when array keys are objects?

@TysonAndre
Copy link
Contributor

I think it sorts by spl_object_id in this PR

@enumag
Copy link

enumag commented Feb 17, 2021

I do not like this RFC at all. It's adding even more complexity to arrays which are already doing many more things than they should. Also with this objects can be only used as keys if they're singletons. It's only a matter of time before another RFC (like 1 or 2) proposes something like an Equatable interface and this will cause BC break concerns because then it would make sense for two equatable objects should be treated as one key.

What I'd be much more happy to see are specialized data structures with the ability to use objects as keys. Currently I'm very happy with using ext-ds for this - two objects can be considered the same using the Hashable interface.

Please let arrays die in peace and come up with something better and faster to replace them with instead - providing new functionality like object keys there.

@anthonyvancauwenberghe
Copy link

@nikic are there any plans on picking this back up and submitting as RFC? I would love to see this in php 8.3.
Kind regards

@dstogov
Copy link
Member

dstogov commented Oct 9, 2023

This wasn't finalized. Now it's outdated, so I'm closing this.

@dstogov dstogov closed this Oct 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants