# How to implement the Python's \`itertools.tee\` function

**URL:** <https://discourse.julialang.org/t/how-to-implement-the-pythons-itertools-tee-function/27142>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [August 4, 2019, 12:56am UTC](https://discourse.julialang.org/t/how-to-implement-the-pythons-itertools-tee-function/27142 "2019-08-04T00:56:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![singularitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/singularitti/32/17678_2.png) [@singularitti](https://discourse.julialang.org/u/singularitti)\
**Post date:** [August 4, 2019, 12:56am UTC](https://discourse.julialang.org/t/how-to-implement-the-pythons-itertools-tee-function/27142/1 "2019-08-04T00:56:48Z")

</div>

Python’s [doc](https://docs.python.org/3.7/library/itertools.html#itertools.tee) has given a roughly equivalent to its `itertools.tee` function:

```python
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?

---

<div class="post-metadata">

**Author:** ![haberdashPI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/haberdashpi/32/26337_2.png) [@haberdashPI](https://discourse.julialang.org/u/haberdashPI)\
**Post date:** [August 4, 2019, 2:14am UTC](https://discourse.julialang.org/t/how-to-implement-the-pythons-itertools-tee-function/27142/2 "2019-08-04T02:14:02Z")

</div>

The most direct translation would be to use [Tasks](https://docs.julialang.org/en/v1/manual/control-flow/#man-tasks-1).

---

<div class="post-metadata">

**Author:** ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)\
**Post date:** [August 4, 2019, 1:53pm UTC](https://discourse.julialang.org/t/how-to-implement-the-pythons-itertools-tee-function/27142/3 "2019-08-04T13:53:37Z")

</div>

> [@haberdashPI](#):
>
> The most direct translation would be to use [Tasks](https://docs.julialang.org/en/v1/manual/control-flow/#man-tasks-1)

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.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [August 5, 2019, 12:37am UTC](https://discourse.julialang.org/t/how-to-implement-the-pythons-itertools-tee-function/27142/4 "2019-08-05T00:37:39Z")

</div>

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

```julia
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) =
    ...

```

See [https://docs.julialang.org/en/latest/manual/interfaces/#man-interface-iteration-1](https://docs.julialang.org/en/latest/manual/interfaces/#man-interface-iteration-1) for how to define `Base.iterate`.

Another approach is to use `@yield` from [ResumableFunctions.jl](https://github.com/BenLauwens/ResumableFunctions.jl).

(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`.)
