-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
WIP: deprecate iteration on bare Associative
, introduce PairIterator
.
#25013
Conversation
Can we please not break iteration and associative arrays just before the release. If you want to experiment with this, you're welcome to make a package and show that your new Abstract type behavior is better. Otherwise, penalizing everyone and forcing them to be explicit in their code for it to do the right thing (and work in generic code contexts like convert and construct) sounds very unfriendly to users. |
813a374
to
91bbfac
Compare
Users should use `pairs(dict)` or `values(dict)` (or `keys(dict)`) to disambiguate iteration result.
91bbfac
to
04507d0
Compare
I'm really intrigued by the indexing unification ideas that you've been working through, @andyferris, but I'm afraid that we just don't have time to let them come to full fruition in Base Julia. I think we can continue to work through them and I can imagine a "Ferrisverse" of packages where we maybe monkey patch Base indexing behavior to have this kind of composability, but I just don't think we should undertake this so close to the 1.0 feature freeze. |
@StefanKarpinski Understood! (I do tend to agree that this is underbaked at this stage). |
FWIW, I'd be in favor of the deprecation – I just had a case where I spent some time debugging a I really would not mind deprecating bare iteration on associatives and being clear about what it is I want to iterate in the short term in exchange for a powerful and unified treatment of iteration and maps over collections in 1.x, rather than 2.0. |
Looking at this again, I take it back since it seems that all this does is require using |
Why? That sounds like a really terrible user experience. |
As I understand it is that different people want dict iteration to be over pairs, values, or keys. By forcing people to specify, it makes it clear what the intent was, and prevents unexpected bugs when the actual does not match what people expected. |
Julia usually tries not to define APIs in this way. This is somewhat reminiscent of the decision in #23233 not to make you specify |
Yes, you've made it clear that this is your opinion. However, we're already getting reports (e.g. from @yurivish) that the difference in how named tuples and dicts iterate has caused confusion and bugs. Forcing people to be explicit about this is a better user experience than that. |
To me, the point of this deprecation is to consider in the future having dictionaries behave as Doing this would be breaking, so deprecation is necessary. The advantage of v0.7/v1.0 is that iteration won't have to stay deprecated for long, whereas if we decide to do this in the future I'm guessing we'll need an entire 2.x release where this is deprecated. (There's also the possibility of deprecating now and backtracking in v1.1 if we decide iterating anything other than pairs by default is crazy). The work to make the value iteration scheme sensible everywhere would require a bit more thought - for instance, we currently And yes, there's also the problem that the status quo is confusing. |
And I was very strongly against this, partly for this reason. I was told repeated that they shouldn't behave the same because a NT is nothing like a Dict. Why is this suddenly a surprise now?
Why is having having two types, one that can do everything the old type used to be able to do (PairIterator) and one that can't (Dict) a better user experience than continuing to use one type (Dict) that does everything? |
To me, the point of this would not be to make dicts and named tuples behave the same. The argument is just that while iterating pairs is useful in some contexts, in other contexts (e.g. |
The other way to look at this is synchronizing the APIs of "indexed collections", i.e. anything that maps indices to values. However I believe that is somewhat blocked on an inherent ambiguity in arrays, where they are sometimes considered to be a simple "series" or "list" of things, and other times considered to be mappings of indices to values. |
What were the results of the latest round of triaging? I believe a change has been merged to |
This wasn't discussed in the last triage call (or two?). |
Oh, sorry. I assumed something was talked about that caused the "triage" label to be removed two days ago. |
Hmm... so it remains a bit ambiguous to me what the triage outcome was here (or if there was a triage outcome / discussion). If there's some appetite for this I can try finish it off - I mostly bring this up because this is one of those things that may be a bit painful to change for v2.0+ |
Here's an odd thought somewhat related to what motivated me with this (being able to do stuff with the values of dictionaries):
Would it be ridiculous to suggest that |
We already have |
Just as a followup note to this PR, we now have this type in base, with a slightly shortened name: With it, I think we've actually nearly arrived at a unification of the dual nature of Arrays and Dictionaries (via |
As a another followup note to this PR, I thought it might be relevant to reference Dictionaries.jl which was recently released, and implements a dictionary interface that iterates values (and supports broadcasting, |
This is WIP towards modifying the iteration scheme for
Associative
. There have been some discussions about whether dictionaries should iterate key-value pairs, or just plain values (like arrays). For my part, I feel the latter makes most sense for operations likemap
(preserves keys),reduce
(such assum(dict)
), and so-on, where you are using the dictionary as an indexed collection of data. Dictionary iteration has been discussed in multiple places - using values was floated by me at #24019, and iteration of dictionary-types is treated pretty extensively at #22194 (named tuples, which iterate values). There, Jeff's opening post contains this observation:With that in mind, in this PR the iteration protocol on
Associative
has been deprecated. A newPairIterator
is introduced, and created bypairs(dict)
. Users should usepairs(dict)
orvalues(dict)
(orkeys(dict)
) to explicitly specify iteration results, like so:The
in
predicate also requires specifyingpairs
,values
orkeys
. This PR doesn't yet fully deal withfilter
andmap
on dictionaries (andpairs
/values
/keys
thereof), but arguably users will want to choose tomap
orfilter
with or without knowing about the key. At some point, it's probably also worth discussing how the deque protocol (push!
, etc) interacts with iteration and the iterator types.This PR also leaves open the possibility of reintroducing an iteration protocol for dictionaries at a later date. Comments very welcome. I will also note that v1.0 is coming up quickly, and we can iterate on this rapidly if we do decide to merge.