diff --git a/NEWS.md b/NEWS.md index d71e14dff6fe1..2da8a7bad8b23 100644 --- a/NEWS.md +++ b/NEWS.md @@ -87,6 +87,7 @@ New library functions * `Sys.username()` can be used to return the current user's username ([#51897]). * `wrap(Array, m::Union{MemoryRef{T}, Memory{T}}, dims)` is the safe counterpart to `unsafe_wrap` ([#52049]). * `GC.logging_enabled()` can be used to test whether GC logging has been enabled via `GC.enable_logging` ([#51647]). +* `IdSet` is now exported from Base and considered public ([#53262]). New library features -------------------- diff --git a/base/exports.jl b/base/exports.jl index b1b84539c07a3..fbb5b449719d6 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -65,6 +65,7 @@ export Missing, NTuple, IdDict, + IdSet, OrdinalRange, Pair, PartialQuickSort, diff --git a/base/iddict.jl b/base/iddict.jl index 0b12ae86b2c6a..9c133d5ba23c6 100644 --- a/base/iddict.jl +++ b/base/iddict.jl @@ -4,11 +4,12 @@ IdDict([itr]) `IdDict{K,V}()` constructs a hash table using [`objectid`](@ref) as hash and -`===` as equality with keys of type `K` and values of type `V`. +`===` as equality with keys of type `K` and values of type `V`. See [`Dict`](@ref) +for further help and [`IdSet`](@ref) for the set version of this. -See [`Dict`](@ref) for further help. In the example below, The `Dict` -keys are all `isequal` and therefore get hashed the same, so they get overwritten. -The `IdDict` hashes by object-id, and thus preserves the 3 different keys. +In the example below, the `Dict` keys are all `isequal` and therefore get hashed +the same, so they get overwritten. The `IdDict` hashes by object-id, and thus +preserves the 3 different keys. # Examples ```julia-repl diff --git a/base/idset.jl b/base/idset.jl index 6e0b7a85a5b23..23f9ca009af0c 100644 --- a/base/idset.jl +++ b/base/idset.jl @@ -1,5 +1,28 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + IdSet{T}([itr]) + IdSet() + +IdSet{T}() constructs a set (see [`Set`](@ref)) using +`===` as equality with values of type `V`. + +In the example below, the values are all `isequal` so they get overwritten. +The `IdSet` compares by `===` so preserves the 3 different keys. + +Examples +≡≡≡≡≡≡≡≡ + +julia> Set(Any[true, 1, 1.0]) +Set{Any} with 1 element: + 1.0 + +julia> IdSet{Any}(Any[true, 1, 1.0]) +IdSet{Any} with 3 elements: + 1.0 + 1 + true +""" mutable struct IdSet{K} <: AbstractSet{K} list::Memory{Any} idxs::Union{Memory{UInt8}, Memory{UInt16}, Memory{UInt32}} diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 909f968b30baf..9d68d55be3459 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -225,14 +225,15 @@ Base.valtype Fully implemented by: - * [`IdDict`](@ref) * [`Dict`](@ref) + * [`IdDict`](@ref) * [`WeakKeyDict`](@ref) Partially implemented by: - * [`BitSet`](@ref) * [`Set`](@ref) + * [`BitSet`](@ref) + * [`IdSet`](@ref) * [`EnvDict`](@ref Base.EnvDict) * [`Array`](@ref) * [`BitArray`](@ref) @@ -246,6 +247,7 @@ Partially implemented by: Base.AbstractSet Base.Set Base.BitSet +Base.IdSet Base.union Base.union! Base.intersect @@ -264,8 +266,10 @@ Base.isdisjoint Fully implemented by: - * [`BitSet`](@ref) * [`Set`](@ref) + * [`BitSet`](@ref) + * [`IdSet`](@ref) + Partially implemented by: diff --git a/stdlib/TOML/src/TOML.jl b/stdlib/TOML/src/TOML.jl index 64d715ceef832..858b75a2e0eff 100644 --- a/stdlib/TOML/src/TOML.jl +++ b/stdlib/TOML/src/TOML.jl @@ -110,7 +110,7 @@ const ParserError = Internals.ParserError """ - print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}) + print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::IdSet{<:AbstractDict}) Write `data` as TOML syntax to the stream `io`. If the keyword argument `sorted` is set to `true`, sort tables according to the function given by the keyword argument `by`. If the keyword argument diff --git a/stdlib/TOML/src/print.jl b/stdlib/TOML/src/print.jl index 06e4f08f35c46..91ea4fd392e4b 100644 --- a/stdlib/TOML/src/print.jl +++ b/stdlib/TOML/src/print.jl @@ -146,7 +146,7 @@ function print_table(f::MbyFunc, io::IO, a::AbstractDict, indent::Int = 0, first_block::Bool = true, sorted::Bool = false, - inline_tables::Base.IdSet, + inline_tables::IdSet, by::Function = identity, ) @@ -223,7 +223,7 @@ end # API # ####### -print(f::MbyFunc, io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print_table(f, io, a; sorted, by, inline_tables) -print(f::MbyFunc, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print(f, stdout, a; sorted, by, inline_tables) -print(io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print_table(nothing, io, a; sorted, by, inline_tables) -print( a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print(nothing, stdout, a; sorted, by, inline_tables) +print(f::MbyFunc, io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print_table(f, io, a; sorted, by, inline_tables) +print(f::MbyFunc, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print(f, stdout, a; sorted, by, inline_tables) +print(io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print_table(nothing, io, a; sorted, by, inline_tables) +print( a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print(nothing, stdout, a; sorted, by, inline_tables) diff --git a/stdlib/TOML/test/print.jl b/stdlib/TOML/test/print.jl index 9698a2871ae27..79a87b9f0f13f 100644 --- a/stdlib/TOML/test/print.jl +++ b/stdlib/TOML/test/print.jl @@ -148,7 +148,7 @@ d = Dict( "y" => inline_dict, "z" => [1,2,3], ) -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, inline_dict) @test toml_str(d; sorted=true, inline_tables) == """ @@ -165,7 +165,7 @@ d = Dict("deps" => Dict( "LocalPkg" => Dict("path" => "LocalPkg"), "Example" => Dict("url" => "https://github.com/JuliaLang/Example.jl"))) -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, d["sources"]["LocalPkg"]) push!(inline_tables, d["sources"]["Example"]) @@ -180,7 +180,7 @@ Example = {url = "https://github.com/JuliaLang/Example.jl"} LocalPkg = {path = "LocalPkg"} """ -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, d["sources"]["LocalPkg"]) s = """ [deps] diff --git a/test/sets.jl b/test/sets.jl index 2e7e19c5c1cdf..c490e66793cb4 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -899,8 +899,8 @@ end b = [2, 3, 1, 3] ua = unique(a) ub = unique(b) - for TA in (Tuple, identity, Set, BitSet, Base.IdSet{Int}), - TB in (Tuple, identity, Set, BitSet, Base.IdSet{Int}), + for TA in (Tuple, identity, Set, BitSet, IdSet{Int}), + TB in (Tuple, identity, Set, BitSet, IdSet{Int}), uA = false:true, uB = false:true A = TA(uA ? ua : a) @@ -921,7 +921,7 @@ end @test !issetequal(B, A) @test !issetequal(B)(A) @test !issetequal(A)(B) - for T = (Tuple, identity, Set, BitSet, Base.IdSet{Int}) + for T = (Tuple, identity, Set, BitSet, IdSet{Int}) @test issetequal(A, T(A)) @test issetequal(B, T(B)) end @@ -982,7 +982,7 @@ end c = [3] d = [4] e = [5] - A = Base.IdSet{Vector{Int}}([a, b, c, d]) + A = IdSet{Vector{Int}}([a, b, c, d]) @test !isempty(A) B = copy(A) @test A ⊆ B