Python generators equivalent?

An API like

s = step(1, 2)
s.next() # 1
s.next() # 3
s.next() # 5

relies upon mutable state. This is obviously impossible with Elixir when using ordinary data structures. Message passing and backing by a genserver could give you something like this, but you’re generally gonna want to avoid that.

There IS a way to get a regular immutable Enumerable to walk forward, but the API is a bit cumbersome because it requires using sort of the “internals” of how Enumerables work.

stream = Stream.cycle([1,2,3])
{:suspended, _, stream} = Enumerable.reduce(stream, {:suspend, nil}, fn(v, _) -> {:suspend, v} end)
{_, val, stream} = stream.({:cont, nil})
val #=> 1
{_, val, stream} = stream.({:cont, nil})
val #=> 2
{_, val, stream} = stream.({:cont, nil})
val #=> 3

Not the prettiest way to do that.

At the end of the day though I’d still say that the closest thing to the python

def step(x, s):
    while True:
        yield x
        x = x + s

Is the Elixir

def step(x, s) do
  Stream.unfold(x, fn(x) -> {x, x+s} end)
end

And the difference in how you use it is just part of the normal differences you get a in a pure vs impure language.