Python’s doc has given a roughly equivalent to its itertools.tee function:
def tee(iterable, n=2):
it = iter(iterable)
deques = [collections.deque() for i in range(n)]
def gen(mydeque):
while True:
if not mydeque: # when the local deque is empty
try:
newval = next(it) # fetch a new value and
except StopIteration:
return
for d in deques: # load it to all the deques
d.append(newval)
yield mydeque.popleft()
return tuple(gen(d) for d in deques)
However, I do not know how to implement the yield keyword. Is there an equivalent way of doing that?
There’s an old pre-1.0 blog post on making iterators using tasks, but I think the “new” (it’s now been a while) iterators interface might make this easier/more idiomatic.
Julia’s yield/yieldto is closer to Python’s await, not Python’s yield (which is more “light weight” as it does not need a task scheduler). For non-IO and non-parallel iterators, I don’t think it’s a good idea to use tasks/channels in Julia.
To implement tee in Julia, you need to do something like
function tee(iter, n=2)
deques = [[] for _ in 1:n]
return [Tee(iter, mydeque, deques) for mydeque in deques]
end
struct Tee{T}
iter::T
mydeque::Vector
deques::Vector{Vector}
end
Base.iterate(iter::Tee, state = nothing) =
...
(Advanced topic: Above approach uses Vector{Any} as mydeque. Using boxed value like this not very optimal and it’s better to use mutate-or-widen approach. But I don’t think it’s possible to do this for deques.)