[Python-Dev] Let's just keep lambda (original) (raw)
Bengt Richter bokr at oz.net
Fri Feb 10 01:16:30 CET 2006
- Previous message: [Python-Dev] Let's just *keep* lambda
- Next message: [Python-Dev] Let's just *keep* lambda
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Thu, 9 Feb 2006 10:33:10 -0800, Guido van Rossum <guido at python.org> wrote:
Enough already.
As has clearly been proven, lambda is already perfect. [...] To those people still complaining that lambda is crippled because it doesn't do statements: First, remember that adding statement capability wouldn't really add any power to the language; lambda is purely syntactic sugar for an anonymous function definition (see above myth debunking section). Second, years of attempts to overcome this haven't come up with a usable syntax (and yes, curly braces have been Yes, but if you're an optimist, those years mean we're closer to the magic moment ;-)
proposed and rejected like everything else). It's a hard problem because switching back to indentation-based parsing inside an expression is problematic. For example, consider this hypothetical example:
a = foo(lambda x, y: print x print y) Should this be considered legal? Or should it be written as a = foo(lambda x, y: print x print y ) Neither. If I may ;-) First, please keep the existing expression lambda exactly as is.
Second, allow a new lambda variant to have a suite. But this necessitates:
same suite syntax as a function def suite, with explicit returns of values except if falling out with a default None. Just like a function def.
diffentiating the variant lambda, and providing for suite termination. 2a. differentiate by using doubled ':' a = foo(lambda x, y :: print x+y) 2b. the lambda:: variant requires enclosing parens, and the top suite ends at the closing ')' A calling context may be sufficient parens, but sometimes, like tuple expressions, yet another pair of enclosing expression-parens may be needed. 2c. Single-line suites terminate on closing paren. Hence a = foo(lambda x, y :: print x; print y) # is ok 2d. For multiline suites, the first line after the one with the '::' defines the column of a single indent (COLSI), at the first non-whitepace character. Further indents work normally and terminate by dedent, or the closing ')' may be placed anywhere convenient to terminate the whole lambda suite. Any statement dedenting to left of the established single indent column (COLSI) before the closing ')' is a syntax error. I recognize that this requires keeping track of independent nested indentation contexts, but that part of tokenizing was always fun, I imagine. I'd volunteer to suffer appropriately if you like this (the lambda variant, I mean, not my suffering ;-)
I think that's it, though I'm always prepared for a d'oh moment ;-)
??? (Indenting the prints so they start at a later column than the 'l' of 'lambda', and adding an explicit dedent before the close parenthesis.) Note that if the former were allowed, we'd have additional ambiguity if foo() took two parameters, e.g.:
a = foo(lambda x, y: print x print y, 42) -- is 42 the second argument to foo() or is it printed? To make 42 a second argument, it would be spelled
a = foo((lambda x, y::
print x
print y), 42)
to have the "print y, 42" statement, you could move the closing paren like
a = foo((lambda x, y::
print x
print y, 42))
but that would have redundant parens with the same meaning as
a = foo(lambda x, y::
print x
print y, 42)
Though perhaps requiring the redundant parens for all (lambda::) expressions would make the grammar easier.
I'd much rather avoid this snake's nest by giving the function a name and using existing statement syntax, like this: This is Python! How can a snake's nest be bad? ;-)
Seriously, with the above indentation rules it seems straightforward to me. I do think it would be hard to do something reasonable without an explicitly differentiated lambda variant though.
def callback(x, y): print x print y a = foo(callback) vs a = foo(lambda x, y :: print x; print y) This is unambiguous, easier to parse (for humans as well as for computers), and doesn't actually span more text lines. Since this Well, it does use more lines when :: allows simple statement suites ;-)
typically happens in a local scope, the name 'callback' disappears as soon as as the scope is exited.
BTW I use the same approach regularly for breaking up long expressions; for example instead of writing a = foo(somecall(anothercall(somelongargument, anotherargument), andmore(1, 2, 3), andstillmore()) I'll write x = anothercall(somelongargument, anotherargument) a = foo(somecall(x, andmore(1, 2, 3)), andstillmore()) and suddenly my code is more compact and yet easier to read! (In real life, I'd use a more meaningful name than 'x', but since the example is nonsense it's hard to come up with a meaningful name here. :-) I can't argue with any of that, except that I think I would like to be able to do both styles. Sometimes it's nice to define right in the context of one-shot use, e.g., I could see writing
ss = sorted(seq, key=(lambda x::
try: return abs(x)
except TypeError: return 0))
(unless I desperately wanted to avoid the LOAD_CONST, MAKE_FUNCTION overhead of using an inline lambda at all. I guess that does favor a global def done once).
Parting shot: it appears that we're getting more and more expressionized versions of statements: first list comprehensions, then generator expressions, most recently conditional expressions, in Python 3000 print() will become a function... Seen this way, lambda was just ahead of its time! Perhaps we could add a try/except/finally expression, and allow assignments in expressions, and then we could rid of statements altogether, turning Python into an expression language. Change the use of parentheses a bit, and... voila, Lisp! :-) Well, if you want to do it, (lambda args::suite) is perhaps a start. I promise not to use it immoderately ;-)
Regards, Bengt Richter
- Previous message: [Python-Dev] Let's just *keep* lambda
- Next message: [Python-Dev] Let's just *keep* lambda
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]