Skip to content

Commit 14ba709

Browse files
committed
Deleted push/pop methods and added tuple support for deletat and insert
1 parent 5c6ac4b commit 14ba709

File tree

2 files changed

+80
-43
lines changed

2 files changed

+80
-43
lines changed

src/ArrayInterface.jl

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using Requires
44
using LinearAlgebra
55
using SparseArrays
66

7-
using Base: OneTo
7+
using Base: OneTo, @propagate_inbounds
88

99
Base.@pure __parameterless_type(T) = Base.typename(T).wrapper
1010
parameterless_type(x) = parameterless_type(typeof(x))
@@ -543,20 +543,6 @@ function restructure(x::Array,y)
543543
reshape(convert(Array,y),size(x)...)
544544
end
545545

546-
"""
547-
push(collection, item)
548-
549-
Return a new instance of `collection` with `item` inserted on the end.
550-
"""
551-
push(collection, x) = vcat(collection, x)
552-
553-
"""
554-
pushfirst(collection, item)
555-
556-
Return a new instance of `collection` with `item` inserted at the beginning.
557-
"""
558-
pushfirst(collection, x) = vcat(x, collection)
559-
560546
"""
561547
insert(collection, index, item)
562548
@@ -577,43 +563,83 @@ Base.@propagate_inbounds function insert(collection, index, item)
577563
return ret
578564
end
579565

580-
"""
581-
pop(collection)
582-
583-
Return a new instance of `collection` with the last item removed.
584-
"""
585-
@inline function pop(collection)
586-
inds = pop(indices(collection))
587-
return @inbounds(getindex(collection, inds))
566+
function insert(x::Tuple, index::Integer, item)
567+
@boundscheck if !checkindex(Bool, static_first(x):static_last(x), index)
568+
throw(BoundsError(x, index))
569+
end
570+
return unsafe_insert(x, Int(index), item)
588571
end
589572

590-
"""
591-
popfirst(collection)
592-
593-
594-
Return a new instance of `collection` with the first item removed.
595-
"""
596-
@inline function popfirst(collection)
597-
inds = popfirst(indices(collection))
598-
return @inbounds(getindex(collection, inds))
573+
@inline function unsafe_insert(x::Tuple, i::Int, item)
574+
if i === 1
575+
return (item, x...)
576+
else
577+
return (first(x), unsafe_insert(Base.tail(x), i - 1, item)...)
578+
end
599579
end
600580

601581
"""
602582
deleteat(collection, index)
603583
604584
Return a new instance of `collection` with the item at the given `index` removed.
605585
"""
606-
Base.@propagate_inbounds function deleteat(collection, index)
607-
@boundscheck checkbounds(collection, index)
608-
ret = similar(collection, length(collection) - 1)
609-
@inbounds for i in indices(ret)
586+
@propagate_inbounds function deleteat(collection::AbstractVector, index)
587+
@boundscheck if !checkindex(Bool, eachindex(collection), index)
588+
throw(BoundsError(collection, index))
589+
end
590+
return unsafe_deleteat(collection, index)
591+
end
592+
@propagate_inbounds function deleteat(collection::Tuple, index)
593+
@boundscheck if !checkindex(Bool, static_first(collection):static_last(collection), index)
594+
throw(BoundsError(collection, index))
595+
end
596+
return unsafe_deleteat(collection, index)
597+
end
598+
599+
function unsafe_deleteat(src::AbstractVector, index::Integer)
600+
dst = similar(src, length(src) - 1)
601+
@inbounds for i in indices(dst)
610602
if i < index
611-
ret[i] = collection[i]
603+
dst[i] = src[i]
612604
else
613-
ret[i] = collection[i + 1]
605+
dst[i] = src[i + 1]
614606
end
615607
end
616-
return ret
608+
return dst
609+
end
610+
611+
@inline function unsafe_deleteat(src::AbstractVector, inds::AbstractVector)
612+
dst = similar(src, length(src) - length(inds))
613+
dst_index = firstindex(dst)
614+
@inbounds for src_index in indices(src)
615+
if !in(src_index, inds)
616+
dst[dst_index] = src[src_index]
617+
dst_index += one(dst_index)
618+
end
619+
end
620+
return dst
621+
end
622+
623+
@inline function unsafe_deleteat(src::Tuple, inds::AbstractVector)
624+
dst = Vector{eltype(src)}(undef, length(src) - length(inds))
625+
dst_index = firstindex(dst)
626+
@inbounds for src_index in OneTo(length(src))
627+
if !in(src_index, inds)
628+
dst[dst_index] = src[src_index]
629+
dst_index += one(dst_index)
630+
end
631+
end
632+
return Tuple(dst)
633+
end
634+
635+
@inline function unsafe_deleteat(x::Tuple, i::Integer)
636+
if i === one(i)
637+
return Base.tail(x)
638+
elseif i == length(x)
639+
return Base.front(x)
640+
else
641+
return (first(x), unsafe_deleteat(Base.tail(x), i - one(i))...)
642+
end
617643
end
618644

619645
function __init__()

test/runtests.jl

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ end
254254
@test !iszero(Static(1))
255255
@test @inferred(one(Static)) === Static(1)
256256
@test @inferred(zero(Static)) === Static(0)
257+
@test eltype(one(Static)) <: Int
257258
# test for ambiguities and correctness
258259
for i [Static(0), Static(1), Static(2), 3]
259260
for j [Static(0), Static(1), Static(2), 3]
@@ -274,11 +275,21 @@ end
274275
end
275276

276277
@testset "push, pushfirst, pop, popfirst, insert, deleteat" begin
277-
@test @inferred(ArrayInterface.push([1,2,3], 4)) == [1, 2, 3, 4]
278-
@test @inferred(ArrayInterface.pushfirst([2,3,4], 1)) == [1, 2, 3, 4]
279-
@test @inferred(ArrayInterface.pop([1, 2, 3, 4])) == [1, 2, 3]
280-
@test @inferred(ArrayInterface.popfirst([1, 2, 3, 4])) == [2, 3, 4]
281278
@test @inferred(ArrayInterface.insert([1,2,3], 2, -2)) == [1, -2, 2, 3]
282279
@test @inferred(ArrayInterface.deleteat([1, 2, 3], 2)) == [1, 3]
280+
281+
@test @inferred(ArrayInterface.deleteat([1, 2, 3], [1, 2])) == [3]
282+
@test @inferred(ArrayInterface.deleteat([1, 2, 3], [1, 3])) == [2]
283+
@test @inferred(ArrayInterface.deleteat([1, 2, 3], [2, 3])) == [1]
284+
285+
286+
@test @inferred(ArrayInterface.insert((1,2,3), 1, -2)) == (-2, 1, 2, 3)
287+
@test @inferred(ArrayInterface.insert((1,2,3), 2, -2)) == (1, -2, 2, 3)
288+
@test @inferred(ArrayInterface.insert((1,2,3), 3, -2)) == (1, 2, -2, 3)
289+
290+
@test @inferred(ArrayInterface.deleteat((1, 2, 3), 1)) == (2, 3)
291+
@test @inferred(ArrayInterface.deleteat((1, 2, 3), 2)) == (1, 3)
292+
@test @inferred(ArrayInterface.deleteat((1, 2, 3), 3)) == (1, 2)
293+
@test ArrayInterface.deleteat((1, 2, 3), [1, 2]) == (3,)
283294
end
284295

0 commit comments

Comments
 (0)