# Tee

Python iterators and Haskell lists are different things. We have not yet had to reckon with this fact, but for this lesson we can no longer look past the distinction.

## Python iterators are mutable

First we’ll set up an example to illustrate why `itertools.tee` exists. Let’s say we start with an iterator that represents all of the natural numbers starting from 1:

``>>> it = count(1)``

And then we define two more iterators based on `it`; one that filters to get only the evens, and another that filters to get only the odds.

``````>>> it_even = filter(lambda x: x % 2 == 0, it)
>>> it_odd  = filter(lambda x: x % 2 == 1, it)``````

If we sample the first five evens and the first five odds, we might hope to get `2,4,6,8,10` for the evens and `1,3,5,7,9` for the odds. But this isn’t what happens:

``````>>> list(islice(it_even, 5))
[2, 4, 6, 8, 10]

>>> list(islice(it_odd, 5))
[11, 13, 15, 17, 19]``````

Why not? Because `it` isn’t really a representation of all the natural numbers starting from 1. It’s more like a mutable database of numbers, and each time something interacts with `it`, it changes. When we first create it, it’s a sequence starting from 1.

``>>> it = count(1)``

But as soon as we apply `next` to it, it’s now a sequence starting from two.

``````>>> next(it)
1``````

And we can observe the change because, the next time we interact with `it`, something different happens.

``````>>> next(it)
2``````

Haskell lists don’t work like this. If we define a list starting at one,

``λ> xs = [1..]``

then the first element in the list is 1, and it is always 1 no matter how many times we ask.

``````λ> head xs
1

1``````

So when we try the even-and-odd experiment again, we get the expected result.

``````λ> xsEven = filter even xs
λ> xsOdd = filter odd xs

λ> take 5 xsEven
[2,4,6,8,10]

λ> take 5 xsOdd
[1,3,5,7,9]``````

## `tee`

For Python iterators, `itertools.tee` is there to deal with this issue. We can use `tee` to fork the original iterator into two copies that each have their own separate internal state.

``````>>> it = count(1)
>>> it_1, it_2 = tee(it, 2)``````

`it_1` and `it_2` are independent; we can use one without affecting the other.

``````>>> it_even = filter(lambda x: x % 2 == 0, it_1)
>>> it_odd = filter(lambda x: x % 2 == 1, it_2)

>>> list(islice(it_even, 5))
[2, 4, 6, 8, 10]

>>> list(islice(it_odd, 5))
[1, 3, 5, 7, 9]``````

This is the last of our lessons on `itertools` functions. Next we’ll move onto other topics!

Join Type Classes for courses and projects to get you started and make you an expert in FP with Haskell.