JuliaCollections / JuliaCollections/IterTools.jl
Iterator slicing/indexing
Nobody has claimed this yet.
- Dominant language
- Julia
- Stars
- 160
- Forks
- 30
- PR merge metrics
- No merged PRs in 30d
Description
Is there a way to slice/index arbitrary iterator in Julia? Can you add a function ("slice") that can do that? It's like Python's itertools.islice and it does
silce(finite_iterator, indices) == collect(finite_iterator)[indices]
but it also works with infinite iterator and indices, provided that indices are strictly increasing (otherwise you need to cache the whole history). I actually coded up a quick implementation:
struct Slice{I, S}
iter::I
slice::S
end
const slice = Slice
mutable struct SliceState
index::Int
iter_state
slice_state
iter_value
end
Base.start(it::Slice) =
SliceState(0, start(it.iter), start(it.slice), nothing)
function Base.done(it::Slice, state)
done(it.slice, state.slice_state) && return true
local x
i = state.index
n, ss = next(it.slice, state.slice_state)
state.slice_state = ss
si = state.iter_state
@assert i < n
while i < n
if done(it.iter, si)
return true
end
x, si = next(it.iter, si)
i += 1
end
state.iter_state = si
state.iter_value = x
state.index = i
return false
end
Base.next(it::Slice, state) = (state.iter_value, state)
Base.iteratorsize(::Type{<: Slice}) = Base.SizeUnknown()
using Base.Test
# @show collect(slice(1:100, 1:2:5))
@test collect(slice(1:100, 1:2:5)) == collect(1:2:5)
@test collect(slice(1:5, 1:2:10)) == collect(1:2:5)
@test collect(slice(1:10, [1, 3, 7, 11])) == [1, 3, 7]
Side notes: Besides obvious lack of documentation and good error message (rather than @assert), the most smelly part of the code is the mutable SliceState and the calls to the next of the underlying iterators. But it seems that this is the usual way to solve this kind of problem for Julia <= 0.6. I guess it's going to be easier with the new iteration protocol for Julia 1.0.
Can IterTools.jl and/or Base already do it? Am I missing something? If not, do you think it is a good API to add in IterTools.jl? I can make a PR with a bit more refined code if you like.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the proposed Slice implementation and Julia's new iteration protocol, including the linked iteration-protocol discussion. Run the shown collect(slice(...)) cases for finite iterators, truncated indices, and non-contiguous indices; done requires an agreed API and implementation that handles the documented finite and infinite iterator cases with useful errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- julia
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100