Reducing "yield from" overhead in recursive generators

Antoon Pardon antoon.pardon at vub.be
Fri Mar 18 05:07:19 EDT 2022


Op 18/03/2022 om 04:14 schreef Rathmann:
> ...
>
> ```python
> def recursive_generator_driver(g):
>      """g is a generator object, which is likely to call other generators"""
>      stack = [g]
>      while True:
>          g = stack[-1]
>          try:
>              val = next(g)
>              if isinstance(val, types.GeneratorType):
>                  # Yielded value represented a recursive call, so push
>                  stack.append(val)
>              else:
>                  # Regular value for iterator, give to caller
>                  yield val
>          except StopIteration:
>              stack.pop()
>              if len(stack) == 0:
>                  return
> ```
>
> and the modified tree traverser is just
>
> ```python
> def inorder_traverse_mod(node):
>      """ONLY for use with recursive_generator_driver"""
>      k, l, r = node
>      if l:
>          yield inorder_traverse_mod(l) # NOT yield from
>      yield k
>      if r:
>          yield inorder_traverse_mod(r) # NOT yield from
> ```
>
> ...
>
> So what do people think of this hack/technique?  Is it
>
> A) A terrible idea?  (Please be specific.)
> B) Already well-known (and I just missed it.)
> C) Potentially useful for the niche case of deeply recursive
>     generators?

I would go with B' + C. It seems there is a resemblance with the trampoline technique
in order to eliminate tail recursion. I know the people of macropy have written a
decorating macro that would eliminate tail recursion from such decorated functions.
Maybe if you contact them they can be interested in making a similar decorating macro
for use with such recursive decorators.

-- 
Antoon Pardon.


More information about the Python-list mailing list