No other language does that, because it makes very little sense. This proposal will make Python behave more like every other programming language that supports anonymous functions.
No other language does that, because it makes very little sense. This proposal will make Python behave more like every other programming language that supports anonymous functions.
Having thought about it for a couple of hours, I don't think there is any good solution for adding multi-line anonymous functions to Python. The suggested syntax feels non-Pythonic, is inherently unexpressive and difficult to read, only useful in a few select use-cases while not solving the holy grail of 'pleasant anonymous functions', and the single problem it's solving isn't common enough or big enough to need dedicated syntax and could already largely be solved with a named function. The fact it enables 'misuse' via Ruby-style iteration, going against Pythonic ideals of 'one way to do things', doesn't work in its favour either.
I don't think analogies with decorators are good either. The advantages of decorators is they transform something otherwise difficult-to-read and unexpressive into something easier-to-read and more expressive, whereas this makes something that's easy-to-read less expressive with the only advantage being terseness. Python, unlike other languages, focuses primarily on clarity over code length.
Haskell is newline-and-indentation-based and allows multi-line anonymous functions.
With that in mind, I often prefer to name functions, but not let them be globally callable, i.e.
f = (g . h) where
g = (2*)
h = (1+)
Does Python allow something like this? (Equivalents in other languages: (defun f (x)
(flet ((g (x) (* 2 x))
(h (x) (1+ x)))
(g (h x))))
Or: sub f {
my $g = sub { 2 * $_[0] };
my $h = sub { 1 + $_[0] };
return $g->($h->($_[0]));
}
I think Haskell is prettiest, but this is not a concept unique to Haskell, and it's a technique I find useful in all three languges.)The Haskell solution is very similar to how Python currently deals with this situation, similar to your Perl and Lisp examples, by allowing named local functions within a block (rather than at statement-level), and also allowing a syntax for single-line anonymous functions (via "lambda").
I did actually ponder a Haskell-like syntax for Python, but decided it's less than ideal. Allowing assignment after a statement makes things more difficult to read, especially in imperative languages.
def f(x):
def g(x): return 2 * x
def h(x): return 1 + x
return g(h(x))
More interesting was your point that Haskell has anonymous functions and is whitespace delimited. I don't think significant whitespace and anonymous functions have any connection at all. function_name(
def(e):
print e
def(f):
print f
)
Now, this isn't inherently terrible and quite easy to read (although could very easily end up in debugging hell), but the problems begin because really you'd also have to allow this: function_name(def(e):
print "e", def(e):
print "f"
)
Which is _really_ ugly, especially as you can't indent it more as it's against Python's (sane) indentation semantics. So this is ruled out.Then you end up with Haskell-style:
function_blah(e, f) where:
e = lambda e: print e
f = lambda f: print f
This has multiple disadvantages for few advantages. Things go from "top-down" to magically changing form to what's underneath changes the statement above. This is suicide in an imperative language, least of all Python. And jumping from lambda to lambda isn't particularly readable either. And you still have to name your lambdas. The current syntax is better.There is the alternative
within blah def e(e):
print e
blah(e)
but this creates messiness where you define a function for blah before blah is defined, which is messy. And you still need a name. And you could accidentally whack out other variable names.So Python's blocks prevent you doing nice multi-line anonymous functions.
So your only choice is to create a special-case solution, as suggested in this post. So you end up thinking:
using blah do (e):
print "e"
Which only passes one. Now, this is less versatile than the other solutions, only allows you to pass a single parameter or anonymous function in, and is less readable - it's simply not /obvious/ what this does unless you know beforehand.But I think something like Ruby's block syntax should be doable, and probably you can even pass multiple blocks, with some limitations on which parameters can receive them. Here's another shot at it, just for fun: http://codepad.org/mVigj978
Having anonymous functions only for the situation where you are passing exactly one of them to another function and it is the last argument is much more arbitrary than the current style of always temporarily binding functions to names.
I don't think either is true -- if you have more flexibility in the syntax, you'll do more with it.
@reg_callback(button.onclick)
def callback():
do_stuff()Read some Ruby code that uses blocks for an example of how passing anonymous functions can become a very clear and natural idiom. In Ruby, you can write your own simple control flow constructs in the form of functions that take a block -- in fact the idiomatic way to iterate through a collection in Ruby is with a function rather than a built-in control flow construct.
In languages like Lisp and Smalltalk, where functions can naturally take more than one in-line block, you can write any control flow construct yourself.