
This list had a proposal last month to make everything an expression, and it has not infrequent attempts to create multi-line lambdas, and I think the reason for this is that people want a better way to create functions that act like Ruby-style blocks since sometimes it makes more sense to write the function that will be passed after the thing it will be passed to and not before. So, here's my proposal. I expect it to get rejected, but hey, someone approved @decorator, so maybe it will make it... Instead of
def decorator(f): ... def inner(*args, **kwargs): ... print(*args, **kwargs) ... return f(*args, **kwargs) ... return inner ...
where the def inner comes before you know what it's going to be used for, why not
def decorator(f): ... return @(*args, **kwargs): ... print(*args, **kwargs) ... return f(*args, **kwargs) ...
? Here's it's very straightforward that what you're doing is returning an anonymous function, and then you find out what's in the function. Similarly,
words = ["blah one", "Blah two", " bLAh three"] sorted(words, key=@(word)): ... word = word.lower() ... word = word.replace("one", "1") ... word = word.replace("two", "2") ... word = word.replace("three", "3") ... word = word.replace(" ", "") ... return word ... [u'blah one', u'Blah two', u' bLAh three']
Which will be equivalent to:
words = ["blah one", "Blah two", " bLAh three"] def key(word): ... word = word.lower() ... word = word.replace("one", "1") ... word = word.replace("two", "2") ... word = word.replace("three", "3") ... word = word.replace(" ", "") ... return word ... sorted(words, key=key) [u'blah one', u'Blah two', u' bLAh three']
Again, I think it's clear here to be told first, "Oh, we're going to sort something" and then learn how the sorting will be done than it is to read a weird function and only after that learn what it's for. Caveats: This shouldn't be allowed to work with two @s in one line. If you have two of them, you should give them names ahead of time with def. This also should not be allowed work inside a for-, if-, with-, or while- statement's initial expression, since the indenting won't work out. Also, myfunc = @(args) should be preemptively banned, since def is the one right way to do it. Also you shouldn't be allowed to do this to make one liners with this (as you can eg. with if-statements), since that's why there's lambda. And using this on the declaration line of a decorator is just crazy. Of course, for all I know, Python's grammar is too simple to make this work with all the caveats, but if it's not, I think this might be a good way to improve readability without killing the indention-based nature of Python that we all know and love. My other thought is that if @ is deemed to be too "Perl-ish" of line noise, def could be used as the keyword instead. Or perhaps a new keyword like "block" or something. That said, I think there is a good analogy here to the existing @-decorator where things are, strictly speaking, written out of order so that the readability is improved and the function that follows is given as an argument to the initial @ line. Thoughts? -- Carl