Favorite non-python language trick?

Christopher Subich spam.csubich+block at block.subich.spam.com
Sun Jul 3 04:28:53 CEST 2005

```Steven D'Aprano wrote:
> On Fri, 01 Jul 2005 12:24:44 -0700, Devan L wrote:
>
>
>>With the exception of reduce(lambda x,y:x*y, sequence), reduce can be
>>replaced with sum, and Guido wants to add a product function.
>
>
> How do you replace:
>
> reduce(lambda x,y: x*y-1/y, sequence)
>
> with sum?

You don't, but an almost equally short replacement works just as well,
and doesn't even need the lambda:
>>>sequence=range(1,100)
>>>_res = 0.0
>>>for x in sequence: _res = _res*x + 1/x
>>><blank line if in interactive mode>
>>>_res
9.3326215443944096e+155

Sure, this isn't a sum, but I'd argue that the for loop solution is
superior:

1) For single expressions, the guts of the operation is still a single line
2) This completely avoids lambda -- while I myself am ambivalent about
the idea of lambda going away, lambda syntax can get hairy for
complicated expressions -- the comma changes meaning halfway through the
expression, from 'parameter delimiter in lambda' to 'next parameter in
reduce'
3) This trivially extends to a block of code, which a lambda doesn't
4) Behavior for zero- and one-length lists is explicit and obvious.

There are, of course, a few disadvantages, but I think they're more
corner corner cases.
1) This solution obviously isn't itself an expression (although the
result is a single variable), so it can't be used in totality as a
component to a larger call.
[Rebuttal: When exactly would this be a good thing, anyway? Reduce
statements are at least 11 characters long, 13 with a one-character
default value.  Using this as a parameter to just about anything else,
even a function call, seems a bit unreadable to me.]
2) An explicit intermediate/result value is needed.  This seems to be
more of a 'cleanliness' argument than anything.

Besides, rewriting this as a for loop actually improves performance:
>>> sequence = range(1,100)
>>> def f1():
j = 0.0
for x in sequence: j = j*x+1/x
return j

>>> def f2():
return reduce(lambda x,y: x*y - 1/y, sequence)
>>> def runtime(f,n):
starttime = time.time()
for i in xrange(n):
f()
print time.time()-starttime
>>> runtime(f1,10000)
1.37199997902
>>> runtime(f2,10000)
3.67499995232

Making the series bigger results in even worse relative performance (no
idea why):
>>> sequence = range(1,1000)
>>> runtime(f1,10000)
18.4169998169
>>> runtime(f2,10000)
125.491000175

So really, 'reduce' is already useless for large anonymous blocks of
code (which can't be defined in lambdas), and it seems slower than 'for
.. in' for even simple expressions.

```