Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[proposal] new ijoin function , an iterable join #102

Open
o314 opened this issue Apr 23, 2023 · 0 comments
Open

[proposal] new ijoin function , an iterable join #102

o314 opened this issue Apr 23, 2023 · 0 comments

Comments

@o314
Copy link

o314 commented Apr 23, 2023

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)))) . :)

@o314 o314 changed the title [proposal] new ijoin function , an iterable join #49373 [proposal] new ijoin function , an iterable join Apr 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant