14

Very rarely I'll come across some code in python that uses an anonymous function which returns an anonymous function...?

Unfortunately I can't find an example on hand, but it usually takes the form like this:

g = lambda x,c: x**c lambda c: c+1

Why would someone do this? Maybe you can give an example that makes sense (I'm not sure the one I made makes any sense).

Edit: Here's an example:

swap = lambda a,x,y:(lambda f=a.__setitem__:(f(x,(a[x],a[y])),
       f(y,a[x][0]),f(x,a[x][1])))()
5
  • 3
    Find and show a real example; that one isn't syntactically correct. Commented Dec 6, 2010 at 0:12
  • produces SyntaxError: invalid syntax. No sense second lambda Commented Dec 6, 2010 at 0:13
  • Why would someone do this? Answer: To irritate others? Commented Dec 6, 2010 at 0:16
  • also, a clearer way to swap two elements of a list is to use tuple unpacking: x[1], x[2] = x[2], x[1] Commented Dec 6, 2010 at 0:19
  • 1
    in generals: lambdas should be used for simple expressions. Chances are, returning anything returning a lambda isn't simple. Commented Dec 6, 2010 at 1:07

8 Answers 8

19

You could use such a construct to do currying:

curry = lambda f, a: lambda x: f(a, x)

You might use it like:

>>> add = lambda x, y: x + y
>>> add5 = curry(add, 5)
>>> add5(3)
8
Sign up to request clarification or add additional context in comments.

Comments

4
swap = lambda a,x,y:(lambda f=a.__setitem__:(f(x,(a[x],a[y])),
       f(y,a[x][0]),f(x,a[x][1])))()

See the () at the end? The inner lambda isn't returned, its called.

The function does the equivalent of

def swap(a, x, y):
     a[x] = (a[x], a[y])
     a[y] = a[x][0]
     a[x] = a[x][1]

But let's suppose that we want to do this in a lambda. We cannot use assignments in a lambda. However, we can call __setitem__ for the same effect.

def swap(a, x, y):
     a.__setitem__(x, (a[x], a[y]))
     a.__setitem__(y, a[x][0])
     a.__setitem__(x, a[x][1])

But for a lambda, we can only have one expression. But since these are function calls we can wrap them up in a tuple

def swap(a, x, y):
     (a.__setitem__(x, (a[x], a[y])),
     a.__setitem__(y, a[x][0]),
     a.__setitem__(x, a[x][1]))

However, all those __setitem__'s are getting me down, so let's factor them out:

def swap(a, x, y):
     f = a.__setitem__
     (f(x, (a[x], a[y])),
     f(y, a[x][0]),
     f(x, a[x][1]))

Dagnamit, I can't get away with adding another assignment! I know let's abuse default parameters.

def swap(a, x, y):
     def inner(f = a.__setitem__):
         (f(x, (a[x], a[y])),
         f(y, a[x][0]),
         f(x, a[x][1]))
     inner()

Ok let's switch over to lambdas:

swap = lambda a, x, y: lambda f = a.__setitem__: (f(x, (a[x], a[y])), f(y, a[x][0]),  f(x, a[x][1]))()

Which brings us back to the original expression (plus/minus typos)

All of this leads back to the question: Why?

The function should have been implemented as

def swap(a, x, y):
    a[x],a[y] = a[y],a[x]

The original author went way out of his way to use a lambda rather then a function. It could be that he doesn't like nested function for some reason. I don't know. All I'll say is its bad code. (unless there is a mysterious justification for it.)

1 Comment

I like how @Winston can think, code, and talk to himself in markup.
2

It can be useful for temporary placeholders. Suppose you have a decorator factory:

@call_logger(log_arguments=True, log_return=False)
def f(a, b):
    pass

You can temporarily replace it with

call_logger = lambda *a, **kw: lambda f: f

It can also be useful if it indirectly returns a lambda:

import collections
collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(int)))

It's also useful for creating callable factories in the Python console.

And just because something is possible doesn't mean that you have to use it.

Comments

2

I did something like this just the other day to disable a test method in a unittest suite.

disable = lambda fn : lambda *args, **kwargs: None

@disable
test_method(self):
    ... test code that I wanted to disable ...

Easy to re-enable it later.

Comments

1

This can be used to pull out some common repetitive code (there are of course other ways to achieve this in python).

Maybe you're writing a a logger, and you need to prepend the level to the log string. You might write something like:

import sys
prefixer = lambda prefix: lambda message: sys.stderr.write(prefix + ":" + message + "\n")
log_error = prefixer("ERROR")
log_warning = prefixer("WARNING")
log_info = prefixer("INFO")
log_debug = prefixer("DEBUG")

log_info("An informative message")
log_error("Oh no, a fatal problem")

This program prints out

   INFO:An informative message
   ERROR:Oh no, a fatal problem

Comments

0

It is most oftenly - at least in code I come accross and that I myself write - used to "freeze" a variable with the value it has at the point the lambda function is created. Otherwise, nonlocals variable reference a variable in the scope they exist, which can lead to undesied results sometimes.

For example, if I want to create a list of ten functions, each one being a multiplier for a scalar from 0 to 9. One might be tempted to write it like this:

>>> a = [(lambda j: i * j) for i in range(10)]
>>> a[9](10)
90

Whoever, if you want to use any of the other factoried functions you get the same result:

>>> a[1](10)
90

That is because the "i" variable inside the lambda is not resolved when the lambda is created. Rather, Python keeps a reference to the "i" in the "for" statement - on the scope it was created (this reference is kept in the lambda function closure). When the lambda is executed, the variable is evaluated, and its value is the final one it had in that scope.

When one uses two nested lambdas like this:

>>> a = [(lambda k: (lambda j: k * j))(i) for i in range(10)]

The "i" variable is evaluated durint the execution of the "for" loop. Itś value is passed to "k" - and "k" is used as the non-local variable in the multiplier function we are factoring out. For each value of i, there will be a different instance of the enclosing lambda function, and a different value for the "k" variable.

So, it is possible to achieve the original intent :

>>> a = [(lambda k: (lambda j: k * j))(i) for i in range(10)]
>>> a[1](10)
10
>>> a[9](10)
90
>>>

1 Comment

Why not use: a = [(lambda k, i=i: i*j) for j in range(10)] instead?
0

It can be used to achieve a more continuation/trampolining style of programming,

See Continuation-passing style

Comments

0

Basically, with this you can modify functions instead of values

One example I stumbled with recently: To compute approximate derivatives (as functions) and use it as an input function in another place.

dx = 1/10**6    
ddx = lambda f: lambda x: (f(x + dx) - f(x))/dx

f = lambda x: foo(x)
newton_method(func=ddx(f), x0=1, n=10)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.