[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