I sing the praises of lambda, my friend and savior!

Steven Bethard steven.bethard at gmail.com
Mon Oct 11 20:30:21 CEST 2004


On Mon, 11 Oct 2004 13:54:29 -0400, Clark C. Evans <cce at clarkevans.com> wrote:
> By this logic, one would make a function,
> 
>  def quadratic(a,b,c):
>      def eval(x):
>          return a*x*x+b*x+c
> 
> and use quadratic(0,2,1,x) where you'd otherwise write (2*x+1)?

No.  Sorry, I obviously wasn't clear here.  The suggestion made to me
was to generalize the function only as much as necessary so that it
could apply to multiple statements *in my code*.  So, while I would
write your 'quadratic' function if my code contained statements like:

func(arg, lambda x: 2*x**2 + 2*x+1)
func(arg, lambda x: 2*x+2)
func(arg, lambda x: 3*x**2+1)

where I truly need the a, b, and c parameters, if my code instead looked like:

func(arg1, lambda x: 2*x+1)
func(arg2, lambda x: 2*x+1)

then I would definitely write it as:

def times2plus1(x):
    return 2*x+1
func(arg1, times2plus1)
func(arg2, times2plus1)

Note that the full 'quadratic' example requires a more verbose, nested
function approach because we want partial function application.  We
could also rewrite the code as something like:

def quadratic(a, b, c, x):
    return a*x**2+b*x+c
func(arg, partial(quadratic, 0, 2, 1))

using partial function application (check the Cookbook for implementation).

Yes, it's still more verbose.  But if you have 30 instances of

func(arg, lambda x: a*x**2+b*x+c) 

each with different a's, b's and c's, and you realize later that these
should all be using a*x**2-b*x-c instead, it's much quicker to fix the
one function than the 30.  =)  On the other hand, if you have only one
instance, I can certainly understand the reluctance.

Out of curiosity, is this quadratic example a real example from your
code, or were you just making this one up?  Just so you know where I
was coming from, the code I changed went from:

self.assertRaises(IndexError, lambda t: t[-10])
self.assertRaises(IndexError, lambda t: t[9])
...
    
to

def getitem(obj, item):
    return obj[item]
self.assertRaises(IndexError, getitem, tree, -10)
self.assertRaises(IndexError, getitem, tree, 9)
...

Note that I had enough assertRaises calls to probably justify this
change -- if I decide later there's something more I should do in
getitem, I can change it in only one place.

> That said, a simple conditional expression would be delightful, as
> I often use mappings (see above) for this sort of logic.

Yeah, I wholeheartedly agree.  (Though of course this one has been
beaten into the ground already, so I won't hold my breath.)

Steve
-- 
You can wordify anything if you just verb it.
        - Bucky Katt, Get Fuzzy



More information about the Python-list mailing list