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.


















