Python: is it possible to combine a generator and a recursive function?

Is there a way to do something like the following code?

add = lambda n: (yield n) or add(n+1)

(answers do not have to be functional)

+5
source share
3 answers
def add(n):
    yield n
    for m in add(n+1):
        yield m

With recursive generators, it’s easy to build complex backtrackers:

def resolve(db, goals, cut_parent=0):
    try:
        head, tail = goals[0], goals[1:]
    except IndexError:
        yield {}
        return
    try:
        predicate = (
            deepcopy(clause)
                for clause in db[head.name]
                    if len(clause) == len(head)
        )
    except KeyError:
        return
    trail = []
    for clause in predicate:
        try:
            unify(head, clause, trail)
            for each in resolve(db, clause.body, cut_parent + 1):
                for each in resolve(db, tail, cut_parent):
                    yield head.subst
        except UnificationFailed:
            continue
        except Cut, cut:
            if cut.parent == cut_parent:
                raise
            break
        finally:
            restore(trail)
    else:
        if is_cut(head):
            raise Cut(cut_parent)

...

for substitutions in resolve(db, query):
    print substitutions

This is a Prolog engine implemented by a recursive generator. db is a dict representing the Prolog database of facts and rules. unify () is a unification function that creates all the substitutions for the current target and adds changes to the trace, so you can undo them later. restore () cancels and is_cut () if the current target is "!", so we can trim the branches.

+3

"yield (n) (n + 1)", , , . , , , " ".

+3

Your function seems to me just another expression for an unrelated sequence:

n, n + 1, n + 2, ....

def add(x):
    while True:
        yield x
        x+=1

for index in add(5):
    if not index<100: break ## do equivalent of range(5,100)
    print(index)

This is not recursive, but I do not see a recursive style here.

A recursive version based on another link reference in which generators called generators, but not recursively:

from __future__ import generators

def range_from(n):
    yield n
    for i in range_from(n+1):
        yield i

for i in range_from(5):
    if not i<100: break ## until 100 (not including)
    print i
0
source

All Articles