diff --git a/base/tuple.jl b/base/tuple.jl index 62e6dbf39eda8..ef3a78fc5098d 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -96,6 +96,33 @@ function indexed_iterate(I, i, state) x end +""" + Base.rest(collection[, itr_state]) + +Generic function for taking the tail of `collection`, starting from a specific iteration +state `itr_state`. Return a `Tuple`, if `collection` itself is a `Tuple`, a `Vector`, if +`collection` is an `AbstractArray` and `Iterators.rest(collection[, itr_state])` otherwise. +Can be overloaded for user-defined collection types to customize the behavior of slurping +in assignments, like `a, b... = collection`. + +!!! compat "Julia 1.6" + `Base.rest` requires at least Julia 1.6. + +# Examples +```jldoctest +julia> a = [1 2; 3 4] +2×2 Matrix{Int64}: + 1 2 + 3 4 + +julia> first, state = iterate(a) +(1, 2) + +julia> first, Base.rest(a, state) +(1, [3, 2, 4]) +``` +""" +function rest end rest(t::Tuple) = t rest(t::Tuple, i::Int) = ntuple(x -> getfield(t, x+i-1), length(t)-i+1) rest(a::Array, i::Int=1) = a[i:end] diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 383dbcda4f93e..347d2d33724d4 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -138,6 +138,7 @@ Base.filter! Base.replace(::Any, ::Pair...) Base.replace(::Base.Callable, ::Any) Base.replace! +Base.rest ``` ## Indexable Collections diff --git a/test/abstractarray.jl b/test/abstractarray.jl index d09e010bfd2f7..cec1d5092a76f 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1193,3 +1193,10 @@ end @test last(itr, 1) == [itr[end]] @test_throws ArgumentError last(itr, -6) end + +@testset "Base.rest" begin + a = reshape(1:4, 2, 2)' + @test Base.rest(a) == a[:] + _, st = iterate(a) + @test Base.rest(a, st) == [3, 2, 4] +end diff --git a/test/tuple.jl b/test/tuple.jl index 21d4932f1ec9b..7f5f16e68fff3 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -575,3 +575,21 @@ end @test_throws BoundsError (1,2.0)[0:1] @test_throws BoundsError (1,2.0)[0:0] end + +@testset "Base.rest" begin + t = (1, 2.0, 0x03, 4f0) + @test Base.rest(t) === t + @test Base.rest(t, 2) === (2.0, 0x03, 4f0) + + a = [1 2; 3 4] + @test Base.rest(a) == a[:] + @test pointer(Base.rest(a)) != pointer(a) + @test Base.rest(a, 3) == [2, 4] + + itr = (-i for i in a) + @test Base.rest(itr) == itr + _, st = iterate(itr) + r = Base.rest(itr, st) + @test r isa Iterators.Rest + @test collect(r) == -[3, 2, 4] +end