From b8d81c78cbce6b588b73d77190a11ef27818564b Mon Sep 17 00:00:00 2001 From: Pablo Zubieta Date: Sun, 29 Jan 2017 16:04:37 -0600 Subject: [PATCH 1/2] Improve inferability of unique --- base/set.jl | 30 +++++++++++++++++++++++++----- test/sets.jl | 3 +++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/base/set.jl b/base/set.jl index 55ba8bab1fff0..e6831bfaf4fe6 100644 --- a/base/set.jl +++ b/base/set.jl @@ -123,16 +123,36 @@ julia> unique([1; 2; 2; 6]) 6 ``` """ -function unique(C) - out = Vector{eltype(C)}() - seen = Set{eltype(C)}() - for x in C +function unique(itr) + T = _default_eltype(typeof(itr)) + out = Vector{T}() + seen = Set{T}() + i = start(itr) + if done(itr, i) + return out + end + x, i = next(itr, i) + if !isleaftype(T) + T = typeof(x) + out = Vector{T}() + seen = Set{T}() + end + push!(seen, x) + push!(out, x) + while !done(itr, i) + x, i = next(itr, i) + S = typeof(x) + if !(S === T || S <: T) + T = typejoin(S, T) + seen = convert(Set{T}, seen) + out = convert(Vector{T}, out) + end if !in(x, seen) push!(seen, x) push!(out, x) end end - out + return out end """ diff --git a/test/sets.jl b/test/sets.jl index f57c7bd9ff24d..c5abf4df21308 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -212,6 +212,9 @@ u = unique([1,1,2]) @test length(u) == 2 @test unique(iseven, [5,1,8,9,3,4,10,7,2,6]) == [5,8] @test unique(n->n % 3, [5,1,8,9,3,4,10,7,2,6]) == [5,1,9] +# issue 20105 +@test @inferred(unique(x for x in 1:1)) == [1] +@test unique(x for x in Any[1,1.0])::Vector{Real} == [1] # allunique @test allunique([]) From 432478d311a141e521074ffb9b3721ff5521cc73 Mon Sep 17 00:00:00 2001 From: Pablo Zubieta Date: Wed, 1 Feb 2017 14:26:04 -0600 Subject: [PATCH 2/2] Put unique loop in another function --- base/set.jl | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/base/set.jl b/base/set.jl index e6831bfaf4fe6..df98cb43174ab 100644 --- a/base/set.jl +++ b/base/set.jl @@ -133,19 +133,28 @@ function unique(itr) end x, i = next(itr, i) if !isleaftype(T) - T = typeof(x) - out = Vector{T}() - seen = Set{T}() + S = typeof(x) + return _unique_from(itr, S[x], Set{S}((x,)), i) end push!(seen, x) push!(out, x) + return unique_from(itr, out, seen, i) +end + +_unique_from(itr, out, seen, i) = unique_from(itr, out, seen, i) +@inline function unique_from{T}(itr, out::Vector{T}, seen, i) while !done(itr, i) x, i = next(itr, i) S = typeof(x) if !(S === T || S <: T) - T = typejoin(S, T) - seen = convert(Set{T}, seen) - out = convert(Vector{T}, out) + R = typejoin(S, T) + seenR = convert(Set{R}, seen) + outR = convert(Vector{R}, out) + if !in(x, seenR) + push!(seenR, x) + push!(outR, x) + end + return _unique_from(itr, outR, seenR, i) end if !in(x, seen) push!(seen, x)