Skip to content

keys(g::Generator) = keys(g.iter) is not generically correct and should not be defined #58341

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

Open
adienes opened this issue May 7, 2025 · 3 comments
Labels
breaking This change will break code collections Data structures holding multiple items, e.g. sets correctness bug ⚠ Bugs that are likely to lead to incorrect results in user code without throwing design Design of APIs or of the language itself

Comments

@adienes
Copy link
Member

adienes commented May 7, 2025

from the keys docstring:

keys(iterator)
For an iterator or collection that has keys and values (e.g. arrays and dictionaries), return an iterator over the keys.

but a Generator does not have keys and values. it only has values. there is no get(::Generator, ...) nor getindex(::Generator, ...)

I believe a similar problem holds for axes(g::Generator) and ndims(g::Generator), but I'm focusing on keys since it seems the most flagrant.

this leads to awful behavior with things like

julia> d
Dict{Symbol, Int64} with 2 entries:
  :a => 1
  :b => -1

julia> findmax(identity, d)
(1, :a)

julia> findmax(Iterators.map(identity, d))
(:b => -1, :b)

where the second call should either error, or maybe a Generator could 1-index as if it were an enumerate so that would become

julia> findmax(Iterators.map(identity, d))
(:b => -1, 2)

note that

julia> iterate(Iterators.map(identity, d))
(:a => 1, 2)

so even the state in iterate is 1-indexed and not taking from keys(g.iter)

I think technically this is a duplicate of #48379, but I don't think the fundamental problem there has anything to do with skipmissing so I just made a new issue.

@adienes adienes added breaking This change will break code design Design of APIs or of the language itself collections Data structures holding multiple items, e.g. sets correctness bug ⚠ Bugs that are likely to lead to incorrect results in user code without throwing labels May 7, 2025
@nsajko
Copy link
Contributor

nsajko commented May 7, 2025

The method was added here, and approved by triage multiple times it seems: #34678

@adienes
Copy link
Member Author

adienes commented May 7, 2025

how unfortunate. well, it's not documented behavior so it's not too late to revert. note that the triage approval summary contained the language doesn't seem harmful.

but it is harmful, as it makes some basic functions in Base violate their docstring.

@jariji
Copy link
Contributor

jariji commented May 7, 2025

Since Generator doesn't implement getindex I don't see a need for it to implement keys. As Takafumi said in the original PR, we should expect

isequal(collect(values(A)), [A[k] for k in keys(A)])

and Generator isn't intended to support random access like that.

So I'd favor an error over the enumerate- or countfrom-style behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code collections Data structures holding multiple items, e.g. sets correctness bug ⚠ Bugs that are likely to lead to incorrect results in user code without throwing design Design of APIs or of the language itself
Projects
None yet
Development

No branches or pull requests

3 participants