From 97364e51b5ebeb972f7fc5c8c2ef9ff7c5116355 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 22 Feb 2014 00:15:01 -0500 Subject: [PATCH 1/3] fix #4996, fix #4871 change Set, IntSet, and PriorityQueue constructors to accept a single iterable add an ObjectIdDict constructor accepting an iterable now you can do this: ``` julia> pairs = [(1,2), (3,4)]; julia> ObjectIdDict(pairs) {1=>2,3=>4} julia> Dict(pairs) [3=>4,1=>2] julia> Collections.PriorityQueue(pairs) [3=>4,1=>2] julia> Set(pairs) Set{(Int64,Int64)}([(1,2),(3,4)]) ``` --- base/array.jl | 2 +- base/collections.jl | 20 ++++++----- base/deprecated.jl | 8 +++-- base/dict.jl | 9 +++++ base/intset.jl | 6 ++-- base/pkg/query.jl | 2 +- base/pkg/resolve/interface.jl | 2 +- base/set.jl | 10 +++--- base/show.jl | 16 ++++----- test/collections.jl | 52 ++++++++++++++-------------- test/perf/kernel/actor_centrality.jl | 2 +- test/perf/spell/perf.jl | 4 +-- 12 files changed, 75 insertions(+), 58 deletions(-) diff --git a/base/array.jl b/base/array.jl index 4b18353621070..625683c800bd2 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1328,7 +1328,7 @@ end # setdiff only accepts two args function setdiff(a, b) args_type = promote_type(eltype(a), eltype(b)) - bset = Set(b...) + bset = Set(b) ret = Array(args_type,0) seen = Set() for a_elem in a diff --git a/base/collections.jl b/base/collections.jl index d14968093d485..9c24d3f5aa82e 100644 --- a/base/collections.jl +++ b/base/collections.jl @@ -124,13 +124,17 @@ type PriorityQueue{K,V} <: Associative{K,V} function PriorityQueue(ks::AbstractArray{K}, vs::AbstractArray{V}, o::Ordering) + # TODO: maybe deprecate if length(ks) != length(vs) error("key and value arrays must have equal lengths") end + PriorityQueue{K,V}(zip(ks, vs)) + end - xs = Array((K, V), length(ks)) + function PriorityQueue(itr, o::Ordering) + xs = Array((K, V), length(itr)) index = Dict{K, Int}() - for (i, (k, v)) in enumerate(zip(ks, vs)) + for (i, (k, v)) in enumerate(itr) xs[i] = (k, v) if haskey(index, k) error("PriorityQueue keys must be unique") @@ -150,15 +154,13 @@ end PriorityQueue(o::Ordering=Forward) = PriorityQueue{Any,Any}(o) -function PriorityQueue{K,V}(ks::AbstractArray{K}, vs::AbstractArray{V}, - o::Ordering=Forward) - PriorityQueue{K,V}(ks, vs, o) -end +# TODO: maybe deprecate +PriorityQueue{K,V}(ks::AbstractArray{K}, vs::AbstractArray{V}, + o::Ordering=Forward) = PriorityQueue{K,V}(ks, vs, o) -function PriorityQueue{K,V}(kvs::Dict{K,V}, o::Ordering=Forward) - PriorityQueue{K,V}([k for k in keys(kvs)], [v for v in values(kvs)], o) -end +PriorityQueue{K,V}(kvs::Associative{K,V}, o::Ordering=Forward) = PriorityQueue{K,V}(kvs, o) +PriorityQueue{K,V}(a::AbstractArray{(K,V)}, o::Ordering=Forward) = PriorityQueue{K,V}(a, o) length(pq::PriorityQueue) = length(pq.xs) isempty(pq::PriorityQueue) = isempty(pq.xs) diff --git a/base/deprecated.jl b/base/deprecated.jl index 3f61a90f2424b..cf1a6089fa300 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -395,6 +395,12 @@ eval(Sys, :(@deprecate shlib_list dllist)) @deprecate put put! @deprecate take take! +@deprecate Set(a, b...) Set({a, b...}) +# for a bit of backwards compatibility +IntSet(xs::Integer...) = (s=IntSet(); for a in xs; push!(s,a); end; s) +Set{T<:Number}(xs::T...) = Set{T}(xs) + + # 0.3 discontinued functions function nnz(X) @@ -402,5 +408,3 @@ function nnz(X) countnz(X) end export nnz - - diff --git a/base/dict.jl b/base/dict.jl index 313aafb497d5a..03f9e2e1c8874 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -152,6 +152,14 @@ push!(t::Associative, key, v) = setindex!(t, v, key) type ObjectIdDict <: Associative{Any,Any} ht::Array{Any,1} ObjectIdDict() = new(cell(32)) + + function ObjectIdDict(itr) + d = ObjectIdDict() + for (k,v) in itr + d[k] = v + end + d + end end similar(d::ObjectIdDict) = ObjectIdDict() @@ -318,6 +326,7 @@ Dict{K }(ks::(K...), vs::Tuple ) = Dict{K ,Any}(ks, vs) Dict{V }(ks::Tuple , vs::(V...)) = Dict{Any,V }(ks, vs) Dict{K,V}(kv::AbstractArray{(K,V)}) = Dict{K,V}(kv) +Dict{K,V}(kv::Associative{K,V}) = Dict{K,V}(kv) similar{K,V}(d::Dict{K,V}) = (K=>V)[] diff --git a/base/intset.jl b/base/intset.jl index 038777b70051c..383be0f6ec88e 100644 --- a/base/intset.jl +++ b/base/intset.jl @@ -6,7 +6,7 @@ type IntSet IntSet() = new(zeros(Uint32,256>>>5), 256, false) end -IntSet(args...) = (s=IntSet(); for a in args; push!(s,a); end; s) +IntSet(itr) = (s=IntSet(); for a in itr; push!(s,a); end; s) similar(s::IntSet) = IntSet() @@ -167,7 +167,7 @@ length(s::IntSet) = int(ccall(:bitvector_count, Uint64, (Ptr{Uint32}, Uint64, Ui (s.fill1s ? typemax(Int) - s.limit : 0) function show(io::IO, s::IntSet) - print(io, "IntSet(") + print(io, "IntSet([") first = true for n in s if n > s.limit @@ -182,7 +182,7 @@ function show(io::IO, s::IntSet) if s.fill1s print(io, ", ..., ", typemax(Int)-1, ")") else - print(io, ")") + print(io, "])") end end diff --git a/base/pkg/query.jl b/base/pkg/query.jl index 85cd4829e0fee..915b0755c67c6 100644 --- a/base/pkg/query.jl +++ b/base/pkg/query.jl @@ -326,7 +326,7 @@ function dependencies_subset(deps::Dict{ByteString,Dict{VersionNumber,Available} end function prune_dependencies(reqs::Requires, deps::Dict{ByteString,Dict{VersionNumber,Available}}) - deps = dependencies_subset(deps, Set{ByteString}(keys(reqs)...)) + deps = dependencies_subset(deps, Set{ByteString}(keys(reqs))) deps, _ = prune_versions(reqs, deps) return deps diff --git a/base/pkg/resolve/interface.jl b/base/pkg/resolve/interface.jl index 1691106ef2f64..d888849e90314 100644 --- a/base/pkg/resolve/interface.jl +++ b/base/pkg/resolve/interface.jl @@ -43,7 +43,7 @@ type Interface function Interface(reqs::Requires, deps::Dict{ByteString,Dict{VersionNumber,Available}}) # generate pkgs - pkgs = sort!(ByteString[Set{ByteString}(keys(deps)...)...]) + pkgs = sort!(ByteString[Set{ByteString}(keys(deps))...]) np = length(pkgs) diff --git a/base/set.jl b/base/set.jl index 692f49dc757e5..fe2aca1c57fa2 100644 --- a/base/set.jl +++ b/base/set.jl @@ -2,13 +2,15 @@ type Set{T} dict::Dict{T,Nothing} Set() = new(Dict{T,Nothing}()) - Set(x...) = union!(new(Dict{T,Nothing}()), x) + Set(itr) = union!(new(Dict{T,Nothing}()), itr) + + # for backwards compat + Set(xs::T...) = Set{T}(xs) end Set() = Set{Any}() -Set(x...) = Set{Any}(x...) -Set{T}(x::T...) = Set{T}(x...) +Set(itr) = Set{eltype(itr)}(itr) -show(io::IO, s::Set) = (show(io, typeof(s)); show_comma_array(io, s,'(',')')) +show(io::IO, s::Set) = (show(io, typeof(s)); show_comma_array(io, s,"([","])")) isempty(s::Set) = isempty(s.dict) length(s::Set) = length(s.dict) diff --git a/base/show.jl b/base/show.jl index 7472b6f13dac9..5f3941e2af356 100644 --- a/base/show.jl +++ b/base/show.jl @@ -212,8 +212,8 @@ print(io::IO, n::Unsigned) = print(io, dec(n)) # original expression. # # This is consistent with many other show methods, i.e.: -# show(Set(1,2,3)) # ==> "Set{Int64}(2,3,1)" -# eval(parse("Set{Int64}(2,3,1)”) # ==> An actual set +# show(Set([1,2,3])) # ==> "Set{Int64}([2,3,1])" +# eval(parse("Set{Int64}([2,3,1])”) # ==> An actual set # While this isn’t true of ALL show methods, it is of all ASTs. typealias ExprNode Union(Expr, QuoteNode, SymbolNode, LineNumberNode, @@ -227,8 +227,8 @@ show_unquoted(io::IO, ex, ::Int,::Int) = show(io, ex) ## AST printing constants ## const indent_width = 4 -const quoted_syms = Set{Symbol}(:(:),:(::),:(:=),:(=),:(==),:(===),:(=>)) -const uni_ops = Set{Symbol}(:(+), :(-), :(!), :(~), :(<:), :(>:)) +const quoted_syms = Set{Symbol}([:(:),:(::),:(:=),:(=),:(==),:(===),:(=>)]) +const uni_ops = Set{Symbol}([:(+), :(-), :(!), :(~), :(<:), :(>:)]) const bin_ops_by_prec = [ "= := += -= *= /= //= .//= .*= ./= \\= .\\= ^= .^= %= .%= |= &= \$= => <<= >>= >>>= ~ .+= .-=", "?", @@ -247,10 +247,10 @@ const bin_ops_by_prec = [ "." ] const bin_op_precs = Dict{Symbol,Int}(merge([{symbol(op)=>i for op=split(bin_ops_by_prec[i])} for i=1:length(bin_ops_by_prec)]...)) -const bin_ops = Set{Symbol}(keys(bin_op_precs)...) -const expr_infix_wide = Set(:(=), :(+=), :(-=), :(*=), :(/=), :(\=), :(&=), - :(|=), :($=), :(>>>=), :(>>=), :(<<=), :(&&), :(||)) -const expr_infix = Set(:(:), :(<:), :(->), :(=>), symbol("::")) +const bin_ops = Set{Symbol}(keys(bin_op_precs)) +const expr_infix_wide = Set([:(=), :(+=), :(-=), :(*=), :(/=), :(\=), :(&=), + :(|=), :($=), :(>>>=), :(>>=), :(<<=), :(&&), :(||)]) +const expr_infix = Set([:(:), :(<:), :(->), :(=>), symbol("::")]) const expr_calls = [:call =>('(',')'), :ref =>('[',']'), :curly =>('{','}')] const expr_parens = [:tuple=>('(',')'), :vcat=>('[',']'), :cell1d=>('{','}'), :hcat =>('[',']'), :row =>('[',']')] diff --git a/test/collections.jl b/test/collections.jl index bdf2c11b206aa..cd75295bef7af 100644 --- a/test/collections.jl +++ b/test/collections.jl @@ -198,24 +198,24 @@ end # isempty @test isempty(Set()) -@test !isempty(Set(1)) -@test !isempty(Set("banana", "apple")) -@test !isempty(Set(1, 1:10, "pear")) +@test !isempty(Set([1])) +@test !isempty(Set(["banana", "apple"])) +@test !isempty(Set({1, 1:10, "pear"})) # ordering -@test Set() < Set(1) -@test Set(1) < Set(1,2) -@test !(Set(3) < Set(1,2)) -@test !(Set(3) > Set(1,2)) -@test Set(1,2,3) > Set(1,2) -@test !(Set(3) <= Set(1,2)) -@test !(Set(3) >= Set(1,2)) -@test Set(1) <= Set(1,2) -@test Set(1,2) <= Set(1,2) -@test Set(1,2) >= Set(1,2) -@test Set(1,2,3) >= Set(1,2) -@test !(Set(1,2,3) >= Set(1,2,4)) -@test !(Set(1,2,3) <= Set(1,2,4)) +@test Set() < Set([1]) +@test Set([1]) < Set([1,2]) +@test !(Set([3]) < Set([1,2])) +@test !(Set([3]) > Set([1,2])) +@test Set([1,2,3]) > Set([1,2]) +@test !(Set([3]) <= Set([1,2])) +@test !(Set([3]) >= Set([1,2])) +@test Set([1]) <= Set([1,2]) +@test Set([1,2]) <= Set([1,2]) +@test Set([1,2]) >= Set([1,2]) +@test Set([1,2,3]) >= Set([1,2]) +@test !(Set([1,2,3]) >= Set([1,2,4])) +@test !(Set([1,2,3]) <= Set([1,2,4])) # add, length s = Set() @@ -236,7 +236,7 @@ end # elements data_in = (1,"banana", ()) -s = Set(data_in...) +s = Set(data_in) data_out = collect(s) @test is(typeof(data_out), Array{Any,1}) @test all(map(d->in(d,data_out), data_in)) @@ -246,15 +246,15 @@ data_out = collect(s) @test length(data_out) == length(data_in) # homogeneous sets -@test is(typeof(Set(1,2,3)), Set{Int}) -@test is(typeof(Set{Int}(3)), Set{Int}) +@test is(typeof(Set([1,2,3])), Set{Int}) +@test is(typeof(Set{Int}([3])), Set{Int}) # eltype -@test is(eltype(Set(1,"hello")), Any) +@test is(eltype(Set({1,"hello"})), Any) @test is(eltype(Set{String}()), String) # no duplicates -s = Set(1,2,3) +s = Set([1,2,3]) @test length(s) == 3 push!(s,2) @test length(s) == 3 @@ -332,16 +332,16 @@ setdiff!(s,(3,5)) @test isequal(s,Set(1,7)) # similar -s = similar(Set(1,"Banana")) +s = similar(Set([1,"Banana"])) @test length(s) == 0 @test typeof(s) == Set{Any} -s = similar(Set{Float32}(2.0f0,3.0f0,4.0f0)) +s = similar(Set{Float32}([2.0f0,3.0f0,4.0f0])) @test length(s) == 0 @test typeof(s) == Set{Float32} # copy data_in = (1,2,9,8,4) -s = Set(data_in...) +s = Set(data_in) c = copy(s) @test isequal(s,c) push!(s,100) @@ -352,7 +352,7 @@ push!(c,200) # start, done, next for data_in in ((7,8,4,5), ("hello", 23, 2.7, (), [], (1,8))) - s = Set(data_in...) + s = Set(data_in) s_new = Set() for el in s @@ -379,7 +379,7 @@ end end # pop! -origs = Set(1,2,3,"apple") +origs = Set([1,2,3,"apple"]) s = copy(origs) for i in 1:length(origs) el = pop!(s) diff --git a/test/perf/kernel/actor_centrality.jl b/test/perf/kernel/actor_centrality.jl index 02d50173e884d..6eaa4b91e7577 100644 --- a/test/perf/kernel/actor_centrality.jl +++ b/test/perf/kernel/actor_centrality.jl @@ -16,7 +16,7 @@ end function centrality_mean(G::Graph, start_node) dists = Dict{Node,Uint64}() - next = Set(G[start_node]) + next = Set([G[start_node]]) cdist = 0 while !isempty(next) diff --git a/test/perf/spell/perf.jl b/test/perf/spell/perf.jl index dfef6aeb59bd5..aed31b560a282 100644 --- a/test/perf/spell/perf.jl +++ b/test/perf/spell/perf.jl @@ -38,7 +38,7 @@ function edits1(word::String) transposes = ["$a$(b[2])$(b[1])$(b[3:end])" for (a,b) in splits[1:end-2]] replaces = ["$a$c$(b[2:end])" for (a,b) in splits[1:end-1], c in alphabet] inserts = ["$a$c$b" for (a,b) in splits, c in alphabet] - return Set(deletes..., transposes..., replaces..., inserts...) + return Set([deletes; transposes; replaces[:]; inserts[:]]) end function known_edits2(word::String) @@ -63,7 +63,7 @@ function correct(word::String) candidates = known([word]) length(candidates) == 0 && (candidates = known(edits1(word))) length(candidates) == 0 && (candidates = known_edits2(word) ) - length(candidates) == 0 && (candidates = Set(word) ) + length(candidates) == 0 && (candidates = Set([word]) ) maximum(x->(get(NWORDS, x, 0),x), candidates)[2] end From 54acc92f7d2cf005aef1c469922436e9fe4aa612 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 22 Feb 2014 13:53:59 -0500 Subject: [PATCH 2/3] show set elements with {} to avoid the concatenation meaning of [] --- base/set.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/set.jl b/base/set.jl index fe2aca1c57fa2..67688186d22b3 100644 --- a/base/set.jl +++ b/base/set.jl @@ -10,7 +10,7 @@ end Set() = Set{Any}() Set(itr) = Set{eltype(itr)}(itr) -show(io::IO, s::Set) = (show(io, typeof(s)); show_comma_array(io, s,"([","])")) +show(io::IO, s::Set) = (show(io, typeof(s)); show_comma_array(io, s,"({","})")) isempty(s::Set) = isempty(s.dict) length(s::Set) = length(s.dict) From 419d198fd7fb18ab823669e9aa75c54c62ad82b6 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 22 Feb 2014 16:59:19 -0500 Subject: [PATCH 3/3] NEWS and doc updates for collection constructor changes --- NEWS.md | 5 +++++ doc/stdlib/base.rst | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index 1be43b20efed6..103961928b0bd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -183,6 +183,9 @@ Library improvements * The `setenv` function for external processes now accepts a `dir` keyword argument for specifying the directory to start the child process in ([#4888]). + * Constructors for collections (`Set`, `Dict`, etc.) now generally accept a + single iterable argument giving the elements of the collection ([#4996], [#4871]) + Deprecated or removed --------------------- @@ -270,6 +273,8 @@ Deprecated or removed [#5748]: https://github.com/JuliaLang/julia/issues/5748 [#5511]: https://github.com/JuliaLang/julia/issues/5511 [#5819]: https://github.com/JuliaLang/julia/issues/5819 +[#4871]: https://github.com/JuliaLang/julia/issues/4871 +[#4996]: https://github.com/JuliaLang/julia/issues/4996 Julia v0.2.0 Release Notes ========================== diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index fef47d4458d08..31bc0703fdd10 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -798,13 +798,14 @@ Partially implemented by: ``IntSet``, ``Set``, ``EnvHash``, ``Array``, ``BitArra Set-Like Collections -------------------- -.. function:: Set(x...) +.. function:: Set([itr]) - Construct a ``Set`` with the given elements. Should be used instead of ``IntSet`` for sparse integer sets, or for sets of arbitrary objects. + Construct a ``Set`` of the values generated by the given iterable object, or an empty set. + Should be used instead of ``IntSet`` for sparse integer sets, or for sets of arbitrary objects. -.. function:: IntSet(i...) +.. function:: IntSet([itr]) - Construct a sorted set of the given integers. Implemented as a bit string, and therefore designed for dense integer sets. If the set will be sparse (for example holding a single very large integer), use ``Set`` instead. + Construct a sorted set of the integers generated by the given iterable object, or an empty set. Implemented as a bit string, and therefore designed for dense integer sets. If the set will be sparse (for example holding a single very large integer), use ``Set`` instead. .. function:: union(s1,s2...)