Hi

C# has a convenient way to create iterators using the `yield return`

statement. The package ResumableFunctions provides the same functionality for the Julia language by introducing the `@resumable`

and the `@yield`

macros. These macros can be used to replace the `Task`

switching functions `produce`

and `consume`

which were deprecated in Julia v0.6. `Channels`

are the preferred way for inter-task communication in julia v0.6+, but their performance is subpar for iterator applications.

```
using ResumableFunctions
@resumable function fibonnaci(n::Int)
a = 0
b = 1
for i in 1:n-1
@yield a
a, b = b, a+b
end
a
end
for fib in fibonnaci(10)
println(fib)
end
```

Enjoy!

Ben

20 Likes

I apologize for being late to the ResumableFunctions vs PyGen party, but for me, the only time I really needed PyGen (because there is no other simple alternative) is when making recursive generators, basically traversing tree-like structures without having to generate it all a priori. So I tested the following pieces of codes in Julia using PyGen and ResumableFunctions and in Python and here are the results:

```
a = [[1,2,3],[4,5,6]]
@resumable function g(x)
if isa(x,Number)
@yield x
else
for i in x
for j in g(i)
@yield j
end
end
end
end
for i in g(a)
println(i)
end
#=
1
false
2
false
3
false
nothing
4
false
5
false
6
false
nothing
nothing
=#
a = [[1,2,3],[4,5,6]]
@pygen function f(x)
if isa(x,Number)
yield(x)
else
for i in x
for j in f(i)
yield(j)
end
end
end
end
for i in f(a)
println(i)
end
#=
1
2
3
4
5
6
=#
import numbers
a = [[1,2,3],[4,5,6]]
def f(x):
if isinstance(x, numbers.Number):
yield x
else:
for i in x:
for j in f(i):
yield j
for i in f(a):
print i
"""
1
2
3
4
5
6
"""
```

Clearly `ResumableFunctions`

generates extra entries not in the other 2, can that be treated?

Hi @mohamed82008

I can explain the behaviour:

- the extra
`false`

entries are a side effect of the transformation of a `for`

loop in a `while`

loop
- the extra
`nothing`

is the normal return of the function (this is also the default behaviour in C#)

Can you open an issue in the `ResumableFunctions`

repository?

The first one can be directly solved. The second one I have to look at the `Iterator`

interface to see if I can fix it.

This is really a very nice use case and I hope I can find a solution;)

Ben

Interesting, I will open an issue then. Thanks for your effort btw, that’s an awesome piece of work!

A complete explanation of this weird but logical behaviour can be found in this issue.

The correct sequence can be created by 3 minor modifications:

```
using ResumableFunctions
@resumable function g(x)
if isa(x,Number)
return x # If x is a number the @resumable function is only called once
else
for i in x
for j in g(i)
j == nothing || @yield j # No explicit return is defined, so we have to eliminate the default returns
end
end
end
end
a = [[1,2,3],[4,5,6]]
for i in g(a)
i==nothing || println(i) # Eliminate the default return
end
```

1 Like