-
-
Notifications
You must be signed in to change notification settings - Fork 671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[js] Enable haxe for-in iteration of js.lib Map and Set #8754
[js] Enable haxe for-in iteration of js.lib Map and Set #8754
Conversation
std/js/lib/Iterator.hx
Outdated
@:forward | ||
abstract Iterator<T>(IteratorStructure<T>) from IteratorStructure<T> { | ||
|
||
public inline function iterator(): JSIterator<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is semantically wrong. It makes js.lib.Iterator
a Haxe's Iterable
.
The difference is the former could be iterated one time, while the latter could be iterated multiple times.
So js.lib.Iterator
should behave like Haxe's Iterator
, which means fields next():T
and hasNext():Bool
should be declared directly on js.lib.Iterator
. But I don't think it's possible because ES6 Iterator already has next
with a different signature.
Though, that's pretty convenient to have iterator()
field on js.lib.Iterable
:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree about the semantic issue, ideally we'd just have next():T
and hasNext()
on the abstract but I couldn't find a way around the collision with the ES6 next()
Maybe the solution here is to rename abstract Iterator
to abstract Iterable
and use that in Set and Map instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To resolve the semantic issue, I've disabled iterating over js.lib.Iterator
(now instead there's a class HaxeIterator
and you have to manually convert it via new HaxeIterator(jsIterator)
)
But iterating over Set and Map will still work and is semantically sound
(I tried lots of approaches to try to resolve the semantic issue with iterating over js.lib.Iterator
however I don't think it's possible to be fully correct here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To enable js.lib.Iterator
iteration you can do
using HaxeIterator;
Which avoids any semantic issues because js.lib.Iterator
still can't unify with StdTypes.Iterable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MapKvIterator
and SetKvIterator
are not needed. You can have inline function iterator() return new HaxeIterator(this.values() /* or this.entries() */)
on both Map
and Set
Edit: Sorry, SetKvIterator
is actually required, because of key:index++
. But Map
s iterator already returns a structure, which is compatible with Haxe's KeyValueIterator
. Try it, please
Also the |
Thanks for reviewing @RealyUniqueName :), I've removed MapKvIterator (not sure why I thought I needed it in the first place 🙃) It would be nice to have a for (key in map.keys()) {
....
} But that requires resolving #8188 so it's something I'll revisit in the future |
This enables using
for-in
onjs.lib.Set
,js.lib.Map
andjs.lib.Iterator
;Impact on Existing Code
None expected
For example, the following will now compile:
For key-value iteration over a Set I've matched the behavior of
haxe.ds.List
To iterate over a
js.lib.Iterator
requires using theHaxeIterator
class:or alternatively
The generated code gets nicely inlined, for key-value iteration on map it looks something like