Open
Description
Hi. This is a proposal for a new feature based on the declension of the well known join
function with an iterable arg.
import Base.Iterators as _I
struct _IJoin
s
delim
end
ijoin(s, delim) = _isijoinable(s) ? _IJoin(s, delim) : throw(ArgumentError("s = $s"))
_isijoinable(s) = _isijoinable(Base.IteratorSize(s))
_isijoinable(::Base.HasLength) = true
_isijoinable(::Base.HasShape{N}) where {N} = N==1
_isijoinable(::Base.IteratorSize) = true
Base.IteratorSize(a::_IJoin) = Base.IteratorSize(a.s)
Base.length(a::_IJoin) = 2*length(a.s)-1
Base.size(a::_IJoin) = let (s1,)=size(a.s); 2*s1-1 end
Base.iterate(a::_IJoin) =
let y=iterate(a.s); y!==nothing ? (y[1], (:yld2,y[2])) : nothing end
Base.iterate(a::_IJoin, (st,sst)) = _iterate(a, Val(st), sst)
_iterate(a::_IJoin, ::Val{:yld2}, sst) =
let y=iterate(a.s, sst); y!==nothing ? (a.delim, (:yld3,sst)) : nothing end
_iterate(a::_IJoin, ::Val{:yld3}, sst) =
let y=iterate(a.s, sst); y!==nothing ? (y[1], (:yld2,y[2])) : nothing end
using Test
import Base.Iterators as _I
@test ijoin(["foo", "bar", "baz"], ".") |> collect == ["foo", ".", "bar", ".", "baz"]
@test ijoin([1,2,3],0) |> collect == [1,0,2,0,3]
@test ijoin((1,2,3),0) |> collect == [1,0,2,0,3]
@test ijoin(1:5,0) |> collect == [1,0,2,0,3,0,4,0,5]
@test _I.dropwhile(<(3),1:5) |> s->ijoin(s,0) |> collect == [3,0,4,0,5]
@test map(ijoin(1:5, 0)) do e; 2e end == [2,0,4,0,6,0,8,0,10]
@test_throws ArgumentError ijoin(fill(1,2,3),0)
# this composes nicely
@test map(ijoin(_I.dropwhile(<(3),1:5), 0)) do e; 2e end |> collect == [6, 0, 8, 0, 10]
# more readably
@test 1:5 |>
s -> _I.dropwhile(<(3),s) |> # == [3, 4, 5]
s -> ijoin(s, 0) |> # == [3, 0, 4, 0, 5]
s -> map(s) do e; 2e end |> # == [6, 0, 8, 0, 10]
collect ==
[6, 0, 8, 0, 10]
This will be useful to work on collections
and i dont like s -> _I.append!([first(s)], _I.flatten(zip(_I.cycle(0), _I.tail(s))))
. :)
Metadata
Metadata
Assignees
Labels
No labels
Activity