Implement setindex for ImmutableDict#59880
Conversation
|
This is a bit misleading since it isn't changing the original dictionary but creating a new one. |
vtjnash
left a comment
There was a problem hiding this comment.
This makes the complexity of ImmutableDict worse than Vector{Pair}, which is never useful
Did you perhaps misread this as
Whenever I make a PR for Julia, it never takes me long to get in over my head... So, take this all with a grain of salt. But the more I look at When I saw I think my main question is whether The most apparent ways it violates the expectations of a dictionary is the behavior of julia> d = Base.ImmutableDict(:a => 1, :b => 2, :a => 3)
Base.ImmutableDict{Symbol, Int64} with 3 entries:
:a => 3
:b => 2
:a => 1
julia> keys(d)
KeySet for a Base.ImmutableDict{Symbol, Int64} with 3 entries. Keys:
:a
:b
:a
julia> values(d)
ValueIterator for a Base.ImmutableDict{Symbol, Int64} with 3 entries. Values:
3
2
1
julia> collect(d)
3-element Vector{Pair{Symbol, Int64}}:
:a => 3
:b => 2
:a => 1I worry that users will iterate over an As another example, consider this: julia> d1 = Base.ImmutableDict(:a => 1, :a => 2)
Base.ImmutableDict{Symbol, Int64} with 2 entries:
:a => 2
:a => 1
julia> d2 = Base.ImmutableDict(:a => 2, :a => 1)
Base.ImmutableDict{Symbol, Int64} with 2 entries:
:a => 1
:a => 2
julia> d1[:a]
2
julia> d2[:a]
1
julia> d1 == d2
trueIs this a bug? No matter whether Getting back to my PR. If function setindex(d::ImmutableDict, value, key)
ImmutableDict(d, key => value)
endseems appropriate, and I can change this PR to do that. But if it is meant to be an immutable dictionary, then my original implementation seems better, despite the higher complexity, because it actually behaves like a dictionary. |
|
It could have been an AssociationList (taking the name from some lisps), to emphasize that implementation detail. But lisps seem to commonly emphasize implementation details rather than the abstract concepts when naming things. Elsewhere it is more common to refer to this as a generalization of a dict, e.g. https://pypi.org/project/multidict/ and https://en.cppreference.com/w/cpp/container/unordered_multimap/find.html and others in https://en.wikipedia.org/wiki/Multimap |
|
The |
This adds a method of `Base.setindex` for `Base.ImmutableDict`, as suggested in JuliaObjects/Accessors.jl#216.
a2de8f0 to
ddcff77
Compare
|
Thanks for the discussion everyone. I updated my implementation of I still think the behavior of I know we can't rename it since it's already public. But I tried to clarify the behavior and usage in the doc string. If you all want that in a separate PR, I'm happy to do that. |
|
I guess one open issue is the equality of |
Several functions and types introduced in Julia 1.13 were missing `!!! compat "Julia 1.13"` annotations in their docstrings, and some were absent from the API reference docs entirely. Add compat notes to: - `Iterators.nth` (base/iterators.jl) - `@__FUNCTION__` (base/runtime_internals.jl) - `Base.AbstractOneTo` (base/range.jl) - `Base.setindex(::ImmutableDict, ...)` (base/dict.jl) - `isassigned(::Tuple, ::Integer)` (base/tuple.jl; also adds docstring) - `Base.active_manifest` (base/initdefs.jl) - `macroexpand` `legacyscope` kwarg and `macroexpand!` (base/expr.jl) - `AbstractSpinLock` and `PaddedSpinLock` (base/locks-mt.jl) - Type annotation support in `gen_call_with_extracted_types` (stdlib/InteractiveUtils/src/macros.jl) Add missing `@docs` entries to the API reference for: - `Base.Iterators.nth` (doc/src/base/iterators.md) - `Base.AbstractOneTo` (doc/src/base/collections.md) - `Base.setindex(::ImmutableDict, ...)` (doc/src/base/collections.md) - `Base.isassigned(::Tuple, ::Integer)` (doc/src/base/arrays.md) - `Base.@acquire` (doc/src/base/parallel.md) - `Base.ScopedValues.AbstractScopedValue` (doc/src/base/scopedvalues.md) - `Base.ScopedValues.LazyScopedValue` (doc/src/base/scopedvalues.md) Also declare `Base.setindex` as public in base/public.jl, which was inadvertently omitted from the original PR (JuliaLang#59880), and fix `nth` → `Iterators.nth` in HISTORY.md following the rename in JuliaLang#61486. Co-Authored-By: Claude <claude@users.noreply.github.com>
Several functions and types introduced in Julia 1.13 were missing `!!! compat "Julia 1.13"` annotations in their docstrings, and some were absent from the API reference docs entirely. Add compat notes to: - `Iterators.nth` (base/iterators.jl) - `@__FUNCTION__` (base/runtime_internals.jl) - `Base.AbstractOneTo` (base/range.jl) - `Base.setindex(::ImmutableDict, ...)` (base/dict.jl) - `isassigned(::Tuple, ::Integer)` (base/tuple.jl; also adds docstring) - `Base.active_manifest` (base/initdefs.jl) - `macroexpand` `legacyscope` kwarg and `macroexpand!` (base/expr.jl) - `AbstractSpinLock` and `PaddedSpinLock` (base/locks-mt.jl) - Type annotation support in `gen_call_with_extracted_types` (stdlib/InteractiveUtils/src/macros.jl) Add missing `@docs` entries to the API reference for: - `Base.Iterators.nth` (doc/src/base/iterators.md) - `Base.AbstractOneTo` (doc/src/base/collections.md) - `Base.setindex(::ImmutableDict, ...)` (doc/src/base/collections.md) - `Base.isassigned(::Tuple, ::Integer)` (doc/src/base/arrays.md) - `Base.@acquire` (doc/src/base/parallel.md) - `Base.ScopedValues.AbstractScopedValue` (doc/src/base/scopedvalues.md) - `Base.ScopedValues.LazyScopedValue` (doc/src/base/scopedvalues.md) Also declare `Base.setindex` as public in base/public.jl, which was inadvertently omitted from the original PR (JuliaLang#59880), and fix `nth` → `Iterators.nth` in HISTORY.md following the rename in JuliaLang#61486. Co-Authored-By: Claude <claude@users.noreply.github.com>
Several functions and types introduced in Julia 1.13 were missing `!!! compat "Julia 1.13"` annotations in their docstrings, and some were absent from the API reference docs entirely. Add compat notes to: - `Iterators.nth` (base/iterators.jl) - `@__FUNCTION__` (base/runtime_internals.jl) - `Base.AbstractOneTo` (base/range.jl) - `Base.setindex(::ImmutableDict, ...)` (base/dict.jl) - `isassigned(::Tuple, ::Integer)` (base/tuple.jl; also adds docstring) - `Base.active_manifest` (base/initdefs.jl) - `macroexpand` `legacyscope` kwarg and `macroexpand!` (base/expr.jl) - `AbstractSpinLock` and `PaddedSpinLock` (base/locks-mt.jl) - Type annotation support in `gen_call_with_extracted_types` (stdlib/InteractiveUtils/src/macros.jl) Add missing `@docs` entries to the API reference for: - `Base.Iterators.nth` (doc/src/base/iterators.md) - `Base.AbstractOneTo` (doc/src/base/collections.md) - `Base.setindex(::ImmutableDict, ...)` (doc/src/base/collections.md) - `Base.isassigned(::Tuple, ::Integer)` (doc/src/base/arrays.md) - `Base.@acquire` (doc/src/base/parallel.md) - `Base.ScopedValues.AbstractScopedValue` (doc/src/base/scopedvalues.md) - `Base.ScopedValues.LazyScopedValue` (doc/src/base/scopedvalues.md) Also declare `Base.setindex` as public in base/public.jl, which was inadvertently omitted from the original PR (JuliaLang#59880), and fix `nth` → `Iterators.nth` in HISTORY.md following the rename in JuliaLang#61486. Co-Authored-By: Claude <claude@users.noreply.github.com>
Several functions and types introduced in Julia 1.13 were missing `!!! compat "Julia 1.13"` annotations in their docstrings, and some were absent from the API reference docs entirely. Add compat notes to: - `Iterators.nth` (base/iterators.jl) - `@__FUNCTION__` (base/runtime_internals.jl) - `Base.AbstractOneTo` (base/range.jl) - `Base.setindex(::ImmutableDict, ...)` (base/dict.jl) - `isassigned(::Tuple, ::Integer)` (base/tuple.jl; also adds docstring) - `Base.active_manifest` (base/initdefs.jl) - `macroexpand` `legacyscope` kwarg and `macroexpand!` (base/expr.jl) - `AbstractSpinLock` and `PaddedSpinLock` (base/locks-mt.jl) - Type annotation support in `gen_call_with_extracted_types` (stdlib/InteractiveUtils/src/macros.jl) Add missing `@docs` entries to the API reference for: - `Base.Iterators.nth` (doc/src/base/iterators.md) - `Base.AbstractOneTo` (doc/src/base/collections.md) - `Base.setindex(::ImmutableDict, ...)` (doc/src/base/collections.md) - `Base.isassigned(::Tuple, ::Integer)` (doc/src/base/arrays.md) - `Base.@acquire` (doc/src/base/parallel.md) - `Base.ScopedValues.AbstractScopedValue` (doc/src/base/scopedvalues.md) - `Base.ScopedValues.LazyScopedValue` (doc/src/base/scopedvalues.md) Also declare `Base.setindex` as public in base/public.jl, which was inadvertently omitted from the original PR (JuliaLang#59880), and fix `nth` → `Iterators.nth` in HISTORY.md following the rename in JuliaLang#61486. Co-Authored-By: Claude <claude@users.noreply.github.com>
This adds a method of
Base.setindexforBase.ImmutableDict, as suggested in JuliaObjects/Accessors.jl#216.For a key that is already in the
ImmutableDict, rather than add it again and shadow it, as described in theImmutableDictdoc string, I opted to exclude the original key and then add in the new one.