In Haskell there is a simple list function available
iterate :: (a -> a) -> a -> [a]
iterate f x = x : iterate f (f x)
In python it could be implemented as following:
def iterate(f, init):
while True:
yield init
init = f(init)
I was kinda surprised that something basic like this is not part of the functools/itertools modules. Could it be simply costructed in functional style (i.e. without the loop) using the tools provided in these libraries? (Mostly code golf, trying to learn about functional style in Python.)
CodePudding user response:
You can do it using some of the functions in itertools
:
from itertools import accumulate, repeat
def iterate(func, initial):
return accumulate(repeat(None), func=lambda tot, _: func(tot), initial=initial)
Although it's clearly not very clean. Itertools is missing some fundamental functions for constructing streams, like unfoldr
. Most of the itertools
functions could be defined in terms of unfoldr
, as it happens, but functional programming is a little uncomfortable in Python anyways so that might not be much of a benefit.
CodePudding user response:
There is a 3rd-party "extension" to the itertools
module, more-iterools
that includes, among many other things, an iterate
function defined exactly like you observed:
# Exact definition, minus the doc string...
def iterate(func, start):
while True:
yield start
start = func(start)
CodePudding user response:
You could use the walrus operator* in a generator expression to get desired output.
from itertools import chain, repeat
def f(x):
return x 10
x = 0
it = chain([x], (x:=f(x) for _ in repeat(None)))
>>> next(it)
0
>>> next(it)
10
>>> next(it)
20