Confessions of a Python fanboy

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Fri Jul 31 20:17:05 CEST 2009


On Fri, 31 Jul 2009 18:15:15 +0200, Masklinn wrote:

> > I know, I know, Ruby people swear by
> > anonymous code blocks, and I've read Paul Graham too. But I'm really
> > not so sure that the benefits of anonymous code blocks are great
> > enough to overcome the disadvantages of anonymous code blocks.
> >
> What are the disadvantages of anonymous functions?

In no particular order, and not necessarily exhaustive:

* The risk of obfuscation in your code. That's fairly minimal for 
lambdas, because they're just a single expression, but for a large 
anonymous code block (ACB) defined inside a named function, it may be 
difficult for the reader to easily distinguish which bits are the outer 
function and which are the ACB.


* Loss of useful debugging information. Take this example from Python:

>>> def main(f):
...     return f(3)
...
>>> main(lambda n: 2/(n-3))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in main
  File "<stdin>", line 1, in <lambda>
ZeroDivisionError: integer division or modulo by zero
>>>
>>> def my_special_function(n):
...     return 2/(n-3)
...
>>> main(my_special_function)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in main
  File "<stdin>", line 2, in my_special_function
ZeroDivisionError: integer division or modulo by zero

If your code has only one anonymous function (whether a lambda or a full 
multi-line block), then it's easy to identify which lambda raised the 
exception: there is only one it could be. But if your code uses lots of 
lambdas, the lack of a function name makes it hard to distinguish one 
<lambda> from another <lambda>. Anonymity makes identification harder.


* Risk of code-duplication and breaking the principle of Once And Only 
Once. Anonymous functions are generally created, used, then immediately 
thrown away -- or at least made more-or-less inaccessible for reuse. An 
anonymous function stored in a callback still exists, but the coder isn't 
able to easily re-use it for another callback somewhere else in the code. 
Consequently, there's a temptation for the coder to write the same 
function multiple times:

add_button("Parrot", colour=blue, callback=lambda x: x.stuff('a'))
add_button("Cheese", flavour=tasty, callback=lambda x: x.thing('b'))
add_button("Canary", colour=yellow, callback=lambda x: x.stuff('a'))

instead of:

def bird_callback(x):
    return x.stuff('a')

add_button("Parrot", colour=blue, callback=bird_callback)
add_button("Cheese", flavour=tasty, callback=lambda x: x.thing('b'))
add_button("Canary", colour=yellow, callback=bird_callback)

* Recursion is more or less impossible without fragile tricks.

(At least for Python. I don't know how recursion operates in Ruby.)





-- 
Steven



More information about the Python-list mailing list