[Python-ideas] Proposal for function expressions
Steven D'Aprano
steve at pearwood.info
Wed Jul 15 02:10:40 CEST 2009
On Wed, 15 Jul 2009 02:56:38 am Chris Perkins wrote:
> For me, avoiding thinking of a name was never the primary motivation
> - putting things in the "right order" is. But I do believe that there
> are situations where the context that a block of code sits in tells
> far more about its purpose that a name ever could - in those
> circumstances, a forced function name can be useless at best, and
> distracting clutter at worst. For example:
>
> y = sorted(x, key=&) do(item):
> name = item.split('-')[1]
> return name.upper()
>
> I think that forcing that two-line block of code to have a name would
> serve no purpose - it's abundantly clear what it does.
I'm afraid I'm with Paul Moore on this one -- it's not clear to me
either.
The key=& seems like a mysterious Perlism -- what's the & operator doing
in there? (Admittedly, it *might* be nice to be able to write things
like reduce(&, alist) instead of reduce(operator.and_, alist). But
that's another story.) "do(item):" confuses me, because it looks like
the start of a do loop, but it isn't.
None of this is to say that I couldn't learn the proposed syntax, but in
my opinion it doesn't mesh well with existing Python constructs.
Did I understand correctly that you prohibited using `if`, `while` and
other block statements inside the do block? If so, then to my mind the
proposal is useless -- it's neither an expression, like the body of
lambda, nor a block, like the body of a function, but a freakish
chimera.
> I also think
> that the current state of affairs encourages poorer readability - I
> mean, admit it, today you would probably write that snippet like
> this:
>
> y = sorted(x, key=lambda item: item.split('-')[0].upper())
>
> which to me loses clarity both by being crammed into one line, and by
> not being able to create the local variable "name", which tells you
> quite a bit about why the the item is being chopped up the way it is.
If I were doing that operation more than once, I'd make a function:
def get_canonical_name(item):
return item.split('-')[0].upper()
and I'd give it a docstring and doctests. The function
get_canonical_name tells you *much* more about why the item is
processed the way it is than a mere local variable "name".
You'll note that I wouldn't bother using a local -- this is short
enough, and simple enough, that I don't need it. But if I only did it
once, then I see nothing wrong with the lambda version. If you're
worried about it being "crammed" into one line:
y = sorted(x, # use the canonical name as the sort key
key=lambda item: item.split('-')[0].upper()
)
works for me.
> Seriously, I guess this is where we differ - I think that improved
> readability _is_ a sufficient goal unto itself. The only question is
> whether other people (OK, one other person in particular) thinks it
> improves readability, and if so, then by how much.
Personally, the only time I've ever missed the ability to create
multi-line lambdas was when I had a series of code blocks like this:
try:
BLOCK
except exception, e:
process_error(e)
where the BLOCK was different in each one, and I really wanted to factor
out the common code into a function "process" and pass each BLOCK as an
argument:
while condition:
process(BLOCK1)
process(BLOCK2)
if something:
process(BLOCK3)
sort of thing.
To my mind, multi-line lambdas are really only useful for the ability to
factor out common code, not to avoid defining a function or spreading
lambdas out over multiple lines.
--
Steven D'Aprano
More information about the Python-ideas
mailing list