On 31 Jul 2009, at 20:17 , Steven D'Aprano wrote:
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.
I believe that one's unadulterated BS.
* 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.
The traceback gives you the line of the anonymous function (even in
python) so unless you have several anonymous functions on the same
line, there's no reason why that would be much of an issue.
Furthermore, Python doesn't provide any more information when the
error happens out of a function (in a `for` or a `with`), so it's not
like there's much of a difference here between Ruby's block-based
approach and Python's statements-based approach.
* 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)
Yes, that one I can give you though I don't think that's a big issue.
And it's not like it's hard to extract the anonymous function into a
named one and then use that on the third strike, so I really don't
believe that point holds much water.
* Recursion is more or less impossible without fragile tricks.
(At least for Python. I don't know how recursion operates in Ruby.)
Code blocks are rarely if ever used recursively. If an operation is
using anonymous functions recursively, then there's often something
very wrong with the idea leading to that code. So I find this
objection irrelevant.
--
http://mail.python.org/mailman/listinfo/python-list