julia> D = Dict{Int32, Float32}
Dict{Int32,Float32}
julia> keytype(D)
Int32
julia> valtype(D)
Float32
julia> P = Pair{Int32, Float32}
Pair{Int32,Float32}
julia> keytype(P)
ERROR: MethodError: no method matching keytype(::Type{Pair{Int32,Float32}})
Closest candidates are:
keytype(::AbstractArray) at abstractarray.jl:124
keytype(::Type{Arrow.Map{K,V,A,B}}) where {K, V, A, B} at /Users/jacobquinn/.julia/dev/Arrow/src/arraytypes.jl:110
keytype(::Type{var"#s91"} where var"#s91"<:(AbstractArray{T,1} where T)) at abstractarray.jl:127
...
Stacktrace:
[1] top-level scope at REPL[83]:1
julia> valtype(P)
ERROR: MethodError: no method matching valtype(::Type{Pair{Int32,Float32}})
Closest candidates are:
valtype(::AbstractArray) at abstractarray.jl:129
valtype(::Type{Arrow.Map{K,V,A,B}}) where {K, V, A, B} at /Users/jacobquinn/.julia/dev/Arrow/src/arraytypes.jl:111
valtype(::Type{var"#s91"} where var"#s91"<:AbstractArray) at abstractarray.jl:147
...
Stacktrace:
[1] top-level scope at REPL[84]:1
Would be a good intro issue if someone wants to take a stab at it.
The intended behavior being keytype(P)
= = Int32
and valtype(P)
== Float32
?
I will try to make a PR for this tonight or tomorrow.
Are the keys not the things one can index with and the values you get by indexing with the keys? How does this fit here?
I see that it would be good to have functions to get those types, but I don't understand how this proposal fits into the concept of keys and values.
Yeah, wouldn't the keytype
always be Int
? Because you index into a pair foo
with foo[1]
and foo[2]
?
So even if you have Pair{String, Float32}
, the keytype
would still be Int
. And the valtype
would be Union{String, Float32}
.
Oh dear, yeah, I guess it isn't as straightforward as I thought. What I was originally posting/wanting is a way to get the K
and V
from Pair{K, V}
, which led me to keytype
and valtype
. In my mind, that was because a Pair
is like a 1-element Dict
, but I didn't think about how it's indexing behavior was so different. @andyferris, any thoughts here?
We may have whiffed a bit here since having a Pair
type is an opportunity to make a really lightweight single-pair dict-like object, whereas treating a pair as a two-element collection is relatively less useful, especially since we already have tuples for this. Marking as 2.0 to consider changing this.
Hmm yeah that鈥檚 interesting, I never considered that option @StefanKarpinski.
I know I _do_ like to destructure pairs like for (k,v) in dict
so how might we handle that case? (I always wondered why we don鈥檛 support for k=>v in dict
so maybe there鈥檚 a bit of syntactic space to play in).
I'm not as big a fan of for (k,v) in dict
. I'd prefer for v in dict
and for (k,v) in pairs(dict)
.
My guess is that people will disagree whether a dict should iterate values or key-value pairs.
That's why I always use for k in keys(dict)
or for v in values(dict)
or for (k, v) in pairs(dict)
.
So personally if it were up to me, I would actually make iteration over dicts undefined, and make people use keys(dict)
or values(dict)
or pairs(dict)
.
But that's just my personal opinion, and I don't think it is relevant to what the language should implement. I don't feel strongly; I'll support whatever the consensus is.
In any of the possible cases I think it would be useful if something equivalent to for (k, v) in pairs(dict)
worked even if we implemented @StefanKarpinski's idea.
Personally, I feel it would be a shame not implementing iteration for dictionaries - there's so much useful stuff you can do via iteration-based APIs. The added boilerplate of wrapping each dictionary in a values
or pairs
every time is a pain, however, and things that are less convenient simply get used less. I favor iterating values
mostly because it matches the array interface and minimizes congnitive overhead in reading and understanding code (which for me at least frequently involves both arrays and dictionaries), and I find that it's the more common access pattern for me whenever doing "data science" oriented work (especially when using Dictionaries.jl where I have access to map
, broadcast
, reduce
, filter
, etc - but I'm biased :slightly_smiling_face:).
If I can try to summarize, a conflict arises with the three-way desire of
Pair
behave like anAbstractDict
with one pair. keytype(::Pair)
and valuetype(::Pair)
of Julia 2.0 would be typeof(first(::Pair))
and typeof(last(::Pair))
of Julia 1.0.for (k, v) in pairs(dict)
AbstractDict
is defined for dicts with more than one pair (regardless of whether it's defined to iterate keys, values, or pairs)Is that right?
Most helpful comment
We may have whiffed a bit here since having a
Pair
type is an opportunity to make a really lightweight single-pair dict-like object, whereas treating a pair as a two-element collection is relatively less useful, especially since we already have tuples for this. Marking as 2.0 to consider changing this.