I tried to implement the sieve of Eratosthenes with iterators (because I wanted to get more into functional programming with python). Sadly some unexpected behaviour occurred. You can see it here in this video: https://imgur.com/gallery/XfXFw4a
Here is my code:
def sieve_primes(stop=10):
L = (x for x in range(2, stop+1))
while True:
prime = next(L)
L = filter(lambda x: x % prime != 0 or x == prime, L)
#L, M = itertools.tee(L)
#print(list(M))
yield prime
It works (spits out an iterator object with the desired primes) when the two commented lines are uncommented. Otherwise, it just iterates over every number.
I'm looking forward to your answers :) Thanks!
def sieve_primes(stop=10):
L = (x for x in range(2, stop+1))
while True:
prime = next(L)
L = filter(lambda x: x % prime != 0 or x == prime, L)
yield prime
What exactly is happening in your code is given below iteration by iteration. For convenience in I represent L as L1 in 1st iteration, L as L2 in 2nd iteration, so on.
In 1st iteration
prime=next(L)
which is 2 (as expected).L1=filter(lambda x: x % prime != 0 or x == prime, L)
(Values ofL
are calculated lazily i.e values calculated only on demand.yield prime
will yield2
expected.In 2nd iteration
prime=next(L1)
. Here comes the tricky part.L1
isfilter object
whose values are calculated only on demand. So, in 2nd iteration whenprime=next(L1)
is executed only one value is calculated fromL
. Now the lambda uses prime as2
and calculates one value which is3
(3%2!=0
) which is nowprime
.L2=filter(lambda x: x % prime != 0 or x == prime, L1)
(Values ofL2
are calculated lazily i.e values calculated only on demand. Now youyield prime
will yield3
.In 3rd iteration
prime=next(L2)
. Now things get little complicated. To get one value fromL2
you need to calculate one value ofL1
and to calculate one valueL1
you need to calculate one valuesL
. If you remember correctlyL
will now yield4
which will now be used byL1
to produce one value. But the latest reference toprime
is3
.4%3!=0
is evaluated toTrue
. So,L1
yields4
. So, calculate the value to be yielded byL2
4%3!=0
is evaluated toTrue
soprime=next(L2)
is4
.
Apply same logic for further iterations you will find 5,6,7,8,9... will be yielded in further iterations.