[Python-3000] genexp syntax for reduce
Boris Borcic
bborcic at gmail.com
Wed Apr 19 18:30:35 CEST 2006
Guido van Rossum wrote:
> I wouldn't recommend this approach to anyone.
What about a variation ? It's arguably a 2.5a1 bug that yield expressions are
permitted in generator expressions, but this suggests a slight syntax extension.
Suppose
wrapper(<EXPR> for <VARS> after <SEEDEXPR> <MORECLAUSES>)
would mean what can in 2.5a1 be clumsily written as
wrapper(<EXPR> for _sd in (<SEEDEXPR>,) for <VARS> in (yield _sd) <MORECLAUSES>)
then, provided adequate wrapper definitions - I'll provide below - one could write
>>> fixpoint(sqrt(x+1) for x after 2) # golden ratio is attractive fixed point
1.6180339887727981
>>> fibo = seedbackloop(x+y for x,y after (1,1))
>>> first10 = lambda gen : tuple(itertools.islice(gen,10))
>>> first10(fibo)
(1, 1, 2, 3, 5, 8, 13, 21, 34, 55)
>>> superfibo = seedbackloop(sum(trio) for trio after (1,1,1))
>>> first10(superfibo)
(1, 1, 1, 3, 5, 9, 17, 31, 57, 105)
>>> data = "put something intelligent here".split()
>>> seedfold(pair for pair after ("Now please",data))
(((('Now please','put'),'something'),'intelligent'),'here')
>>> seedfold([y,x] for x,y after ("Now please",data))
['here',['intelligent',['something',['put','Now please']]]]
Here for proof-of-concept definitions of the wrappers (without attention to
corner cases/error messages, but tested with the above examples through the
2.5a1 equivalent syntax)
def seedfold(gen) :
from itertools import repeat
feedback,source = gen.next()
source = iter(source)
next = source.next()
feedback = gen.send((feedback,next) for _ in repeat(None))
for next in source :
feedback = gen.next()
return feedback
def seedbackloop(gen) :
from collections import deque
from itertools import repeat
feedback = deque(gen.next())
for item in feedback :
yield item
feedback.append(gen.send(tuple(feedback) for _ in repeat(None)))
while True :
feedback.popleft()
yield feedback[-1]
feedback.append(gen.next())
def fixpoint(gen,maxiter=1000,eps=1e-10) :
from itertools import repeat
cnt = maxiter
anterior = gen.next()
posterior = gen.send(anterior for _ in repeat(None))
while abs(posterior-anterior)>eps :
cnt -= 1
if cnt == 0 :
raise ValueError("Expression did not converge after "
+ str(maxiter) + " iterations")
anterior = posterior
posterior = gen.next()
return posterior
Regards, Boris Borcic
--
assert "304" in "340343", "P4R4D15E M15M47C8"
More information about the Python-3000
mailing list