#>>>>>>>>>> Icon example of recursive generator >>>>>>>>> ##procedure star(chars) ## suspend "" | (star(chars) || !chars) ##end ## class bang(object): """ a generator with saved state that can be reset """ def __init__(self, arg): self.arg = arg self.reset() def __iter__(self): for item in self.iterable: yield item def next(self): return self.iterable.next() def reset(self): if hasattr(self.arg, '__iter__') and \ hasattr(self.arg, 'next') : self.iterable = self.arg elif hasattr(self.arg, '__getitem__'): if self.arg: self.iterable = iter(self.arg) else: self.iterable = iter([""]) else: self.iterable = iter([self.arg]) def __repr__(self): return repr(self.arg) def alternation( *items ): """Lazy evaluation that flattens input items """ for alt_item in items: if hasattr(alt_item, '__iter__'): #flatten generator item for item in alt_item: yield item else: yield alt_item def concatenate(g1, g2): """Lazy evaluation concatenation """ #list, tuple, and string iterators are not used implicitly #Not generalized for sequences other than strings if hasattr(g1, '__iter__') and hasattr(g2, '__iter__'): #concatenations of left items to right items #map(operator.plus, leftseq, rightseq) for x in g1: g2.reset() for y in g2: yield x + y elif hasattr(g1, '__iter__') : #concatenations of left items to right sequence #map(operator.plus, [leftseq]*len(rightseq), rightseq) for x in g1: yield x + g2 elif hasattr(g2, '__iter__') : #concatenations of left sequence to right items #map(operator.plus, leftseq, [rightseq]*len(leftseq)) for x in g2: yield g1 + x else: #string concatenation like Python yield g1 + g2 def star(chars): """ Recursive, infinite generator for all permutations of a string taken 1 to N characters at time """ for item in alternation("", concatenate(star(chars), bang(chars))): yield item #star test >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> chars = 'abc' limit = 3 # Limit infinite recursion for n, x in enumerate(star(chars)): if len(x) > limit: break print n+1, repr(x)