From 761cf9cf775eb7cdd9eab0c346c34e5e780f53bf Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 1 Feb 2017 10:04:12 -0600 Subject: [PATCH] RFC: exportable tuple-manipulation utilities --- base/exports.jl | 2 ++ base/tuple.jl | 36 ++++++++++++++++++++++++++++++++++++ test/tuple.jl | 3 +++ 3 files changed, 41 insertions(+) diff --git a/base/exports.jl b/base/exports.jl index 736038da9e5cc..9265b4bef97d1 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -86,6 +86,8 @@ export Range, RangeIndex, Rational, + ReferenceBack, + ReferenceFront, Regex, RegexMatch, RemoteChannel, diff --git a/base/tuple.jl b/base/tuple.jl index 5a6a1ba5b2d7e..6cda152d48f3e 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -76,6 +76,42 @@ function _front(out, v, t...) _front((out..., v), t...) end +abstract ReferenceTuple +immutable ReferenceFront{TT<:Tuple} <: ReferenceTuple + t::TT +end +immutable ReferenceBack{TT<:Tuple} <: ReferenceTuple + t::TT +end + +""" + split(t, ReferenceFront(ref)) -> front, back + +Splits a tuple or CartesianIndex `t` into two pieces, `front` and +`back`, such that `t == (front..., back...)`. `front` has the same +length as the reference `ref`. +""" +split(t::Tuple, ref::ReferenceFront) = _splitfront((), t, ref.t) +_splitfront{N}(out::NTuple{N}, t, ref::NTuple{N}) = out, t +_splitfront(out, ::Tuple{}, ref) = + (@_noinline_meta; throw(DimensionMismatch("front reference had $(length(ref)) elements, but input had only $(length(out))"))) +_splitfront(out, t, ref) = + (@_inline_meta; _splitfront((out..., t[1]), tail(t), ref)) + +""" + split(t, ReferenceBack(ref)) -> front, back + +Splits a tuple or CartesianIndex `t` into two pieces, `front` and +`back`, such that `t == (front..., back...)`. `front` has the same +length as the reference `ref`. +""" +split(t::Tuple, ref::ReferenceBack) = _splitback((), t, ref.t) +_splitback{N}(out, t::NTuple{N}, ref::NTuple{N}) = out, t +_splitback(out, ::Tuple{}, ref) = + (@_noinline_meta; throw(DimensionMismatch("back reference had $(length(ref)) elements, but input had only $(length(out))"))) +_splitback(out, t, ref) = + (@_inline_meta; _splitback((out..., t[1]), tail(t), ref)) + ## mapping ## """ diff --git a/test/tuple.jl b/test/tuple.jl index 4470ac6992257..6ccef0261f53b 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -231,3 +231,6 @@ end @test Tuple{Int,Vararg{Any}}(Float64[1,2,3]) === (1, 2.0, 3.0) @test Tuple(ones(5)) === (1.0,1.0,1.0,1.0,1.0) @test_throws MethodError convert(Tuple, ones(5)) + +@test @inferred(split((1,2,3), ReferenceFront((5,5)))) === ((1,2), (3,)) +@test @inferred(split((1,2,3), ReferenceBack((5,5)))) === ((1,), (2,3))