[Python-3000] genexp syntax for reduce (already in 2.5a1)

Boris Borcic boris at batiment71.net
Tue Apr 18 14:06:17 CEST 2006


Hello,

Since the notion of a "generator comprehension" reduce syntax for py3k was
discussed on this list - it may have escaped attention that py2.5a1 already
allows the following, admittedly not very efficient (nor too robust in this
proof-of-concept implementation).

hth, Boris Borcic


def ireduce(gen) :
     """
     Generator expression syntax for reduce and generalizations

     Usage examples:

     - (yield) nothing as below if there is no seed value
     *and* the expression consists of a single arithmetic op

     >>> ireduce(x+(yield) for x in range(101)) # famous Gauss example
     5050
     >>> ireduce(x*(yield) for x in range(1,6))
     120

     - if there is a seed, yield it (unless it's None)

     >>> ireduce(x*(yield 2) for x in range(1,6)) # 2*1*2*3*4*5
     240
     >>> ireduce(x*(yield 2) for x in range(2,6)) # 2*2*3*4*5
     240
     >>> ireduce(x*(yield 2) for x in range(6))   # 2*0*1*2*3*4*5
     0

     - if the seed is None, (yield INone) instead

     >>> ireduce((x,(yield INone)) for x in "for all good men".split())
     ('men', ('good', ('all', ('for', None))))

     >>> ireduce([(yield INone),x] for x in "for all good men".split())
     [[[[None, 'for'], 'all'], 'good'], 'men']

     - do as below if you want no special seed and the operation to reduce
     isn't a simple arithmetic operation

     >>> ireduce((x,(yield Seed(x))) for x in "for all good men".split())
     ('men', ('good', ('all', 'for')))

     >>> ireduce(x+' '+(yield Seed(x)) for x in "for all good men".split())
     'men good all for'

     >>> ireduce({ x : (yield Seed(x))} for x in "for all good men".split())
     {'men': {'good': {'all': 'for'}}}

     - and notice these for a comparison

     >>> ireduce({ x : (yield x)} for x in "for all good men".split())
     {'men': {'good': {'all': {'for': 'for'}}}}

     >>> ireduce({ x : (yield Seed(None))} for x in "for all good men".split())
     {'men': {'good': {'all': None}}}
     """

     cumulate = gen.next()
     if cumulate is None :
         cumulate = Neutral()
     elif cumulate is INone :
         cumulate = None
     elif isinstance(cumulate,Seed) :
         cumulate = cumulate.seed
         gen.send(cumulate)
         gen.next()
     try :
         while True :
             cumulate = gen.send(cumulate)
             gen.next()
     except StopIteration :
         return cumulate

class Neutral : # this would need reworking
     def __coerce__(self,other) :
         self.other = other
         return (self,self)

     def __getattr__(self,attr) :
         return lambda *x,**y : self.__dict__['other']

class INone : pass

class Seed :
     def __init__(self,seed) :
         self.seed = seed




More information about the Python-3000 mailing list