I just put together a type that caches the values of a (possibly infinite)
iterator, that I wanted to through up here in case its useful for others.
It assumes that the state of the input iterator is type stable. Any
suggestions for improving efficiency are welcome.
## Cache iterator
type CachedIterator{T,IT,ST}
iterator::IT
storage::Vector{T}
state::ST
length::Int
CachedIterator(it::IT) = new(it,Vector{it}(),start(it),0)
end
CachedIterator(it) =
CachedIterator{eltype(it),typeof(it),typeof(start(it))}(it)
function Base.resize!(it::CachedIterator,n::Integer)
m = it.length
if n > m
if n > length(it.storage)
resize!(it.storage,2n)
end
for k = m+1:n
if done(it.iterator,it.state)
it.length = k-1
return it
end
val,it.state = next(it.iterator,it.state)
@inbounds it.storage[k] = val
end
it.length = n
end
it
end
Base.eltype{T}(it::CachedIterator{T}) = T
Base.start(it::CachedIterator) = 1
Base.next(it::CachedIterator,st::Int) = (it[st],st+1)
Base.done(it::CachedIterator,st::Int) = st == it.length + 1 &&
done(it.iterator,it.state)
Base.getindex(it::CachedIterator,k::Int) = resize!(it,k).storage[k]