Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

The lambda construct is used to invoke a function, where the name of the function is given, then forgotten / not needed any more. A parallel situation occurs with variables, for instance in the following generation of ten random numbers:

import random
print [ random.choice( [0..1000] ) for extractionCounter in [1..10] ]

(I've got this time [933, 708, 641, 729, 455, 854, 673, 581, 955, 472].) Now, some economical spirit argues, that we do not need the extractionCounter as it is or as a k or an other name of a variable. And eclipse marks the corresponding line with the hint (!) "unused variable". Then we can simply use instead:

import random
print [ random.choice( [0..1000] ) for _ in [1..10] ]

and a mathematician will complain usually for writing a list by using the "white noise letter" _ and consider this line as an ugly trick. But programmers love this.

An other paradigm would be to define a variable, use it in the next line, and never again. For instance:

p = 2
q = p^32
F = GF(q)

Usually, we will need in the sequel p, q . But if we do not need them, it is better to use directly F = GF( 2^32 ) . Both versions are interpreted, but there are coding guidelines, and styles. One proverb in python is "explicit is better than implicit", so F = GF( 2^32 ) is best in this sense.

Now there are similar issues, where we need a function (instead of a variable), but for a short usage. And the function is a minor appearance in our theater with quick interpreters of a clean language. In that case, the underscore is not welcome. We use the lambda construction. Instead of

def myFunction( y ):
     if condition(y):
         return doSomethingWith( y )
     return 0

followed by a single use of the function myFunction, we want direct solution. We need such an example of a singel usage. Note that the single usage may have to "unnatural" in the context. For instance, instead of

winner = myFunction( y )

we could and should maybe have used

winner = doSomethingElse( y ) if condition(y) else 0

and there is no need for a function. So when would we have such a "more complicated", "unnatural" situation?! Such a possible situation is given by a function, that expects an other function as one of its arguments. (Function have names, and are "regular citizens" in python.) In math we have often to deal with... plotting a function. We take it as an exampe. It we have such a customized function, myPlot( fun, interval ), then we may define myFunction as above and call

myPlot( myFunction, interval )

But as a quick line we may want to use:

myPlot( lambda y: doSomethingElse( y ) if condition(y) else 0 , interval )

An other reason to use the lambda construction is in the case of

def myFunction( a, b, y ):
     return doThisAndThat( a, b ) - doSomethingElse( y )

where a, b are parameters. And we want to plot w.r.t y. We simply define the above function to have a clear separation of plot and formulas, then use it simply:

    myPlot( lambda y: myFunction( a, b, y ), interval )    # a, b must be interpretable at this point

Very often, one uses lambda functions in sort(ing) operations. For instance:

sage: E = EllipticCurve( [-65, 0] )
sage: integral_points = E.integral_points()
sage: integral_points.sort( lambda P,Q:    cmp( abs(P[0]), abs(Q[0]) ) )
sage: integral_points
[(0 : 0 : 1), (-1 : 8 : 1), (-4 : 14 : 1), (9 : 12 : 1), (65 : 520 : 1)]

(I want quickly the points, no time to introduce the sorting function.) An other example is as follows: There is a difference between the following two lines...

sage: plot( lambda x:    max( abs(x-1), 1, x**2 ), -2, 2 )
sage: plot( max( abs(x-1), 1, x**2 ), -2, 2 )

And now back to the example in the question. This is really an example where we need the name of the function. So i would personally prefer:

def pi(x):
    """Here is a good point to introduce some ten
    lines of comments, doc strings are important.
    return pari(x) . primepi()

(Even if there is a single or no usage of pi. Unfortunately, there is a name collision, so we should isolate this pi in its own namespace, a class or a function, for instance.)