2010-07-18 9 views

Respuesta

3
def add(n): 
    yield n 
    for m in add(n+1): 
     yield m 

Con los generadores recursivas que es fácil de construir backtrackers elaborados:

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 

Este es un motor Prolog implementado por un generador recursivo. db es un dict que representa una base de datos Prolog de hechos y reglas. unify() es la función de unificación que crea todas las sustituciones para el objetivo actual y agrega los cambios al camino, por lo que se pueden deshacer más adelante. restore() realiza las pruebas de deshacer e is_cut() si el objetivo actual es un '!', por lo que podemos hacer una poda de ramas.

+0

El ejemplo de agregar dado no tiene una condición de terminación. ¿Lo intentaste? – Alice

3

No estoy seguro de la intención de "rendimiento (n) o añadir (n + 1)", pero recursivos son generadores ciertamente posible. Es posible que desee leer el siguiente enlace para obtener más información sobre lo que es posible, en particular la sección titulada "Generadores recursivos".

0

Su función parece a mí sólo para estar otra expresión para la secuencia no unido:

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) 

Esto no es recursivo, pero no veo la necesidad de un estilo recursivo aquí.

La versión recursiva basada en el enlace de otras respuestas, que tenían generadores de llamar a los generadores, pero no de forma recursiva:

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 
Cuestiones relacionadas