[Python-ideas] Statement local functions and classes (aka PEP 3150 is dead, say 'Hi!' to PEP 403)
Eric Snow
ericsnowcurrently at gmail.com
Thu Oct 13 08:33:22 CEST 2011
On Wed, Oct 12, 2011 at 11:48 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On Thu, Oct 13, 2011 at 2:45 PM, Carl M. Johnson
> <cmjohnson.mailinglist at gmail.com> wrote:
>> I really like the proposal, although I would be interested to see if anyone can bikeshed up keywords that might be better than : or @… :-)
>>
>> I do have some questions about it. Does using @ instead of the name defined below make the implementation easier? In other words, would this cause a NameError on normalize because normalize isn't defined in the local namespace?--
>>
>> :sorted_list = sorted(original, key=normalize)
>> def normalize(item):
>> …
>>
>> Or is the @ just for brevity? I assume the point is that it's not just brevity, but you have to use the @ in order to make the implementation straightforward.
>
> The brevity and highlighting the "forward reference" are actually the
> primary motivation, making the implementation easier (which it does
> do) is a nice bonus.
>
> When I first started writing up the PEP, I was using a syntax more
> directly inspired by PEP 3150's given clause:
>
> :sorted_list = sorted(original, key=@) given (item):
> …
>
> There were a few problems with this:
> 1. It pushes the signature of the callable all the way over to the RHS
> 2. The callable is actually anonymous, so @.__name__ would always be
> "<given>". That's annoying for the same reason as it's annoying in
> lambda expressions.
> 3. It doesn't provide any real clues that the body of the statement is
> actually a nested function
>
> So then I thought, "well what if I use 'def' instead of 'given' as the
> keyword"? At that point, it was only a short leap to realising that
> what I wanted was really close to "arbitrary simple statement as a
> decorator". So I rewrote things to the format in the posted PEP:
>
> :sorted_list = sorted(original, key=@)
> def normalise(item):
> …
>
> Now that the nested function is being given a name, I realised I
> *could* just refer to it by that name in the block prefix. However, I
> left it alone for the reasons I mention above:
>
> 1. It highlights that this is not a normal name reference but
> something special (i.e. a forward reference to the object defined by
> the statement)
> 2. The fact that references are always a single character makes it
> easier to justify giving the function itself a nice name, which
> improves introspection support and error messages. In genuine
> throwaway cases, you can always use a dummy name like 'f', 'func',
> 'g', 'gen' or 'block' or 'attr' depending on what you're doing.
> 3. Multiple references don't make the block prefix unwieldy (although
> the use cases for those are limited)
> 4. It does make the implementation easier, since you don't have to
> worry about namespace clashes - the function remains effectively
> anonymous in the containing scope.
I like it a lot better as a symbol than as an identifier. It visually pops out.
>
> It would be possible to extend the PEP to include the idea of allowing
> the name to be omitted in function and class definitions, but that's
> an awful lot of complexity when it's easy to use a throwaway name if
> you genuinely don't care.
easy:
:sorted_list = sorted(original, key=@)
def _(item):
…
-eric
>
> Just like PEP 3150, all of this is based on the premise that one of
> the key benefits of multi-line lambdas is that it lets you do things
> in the *right order* - operation first, callable second. Ordinary
> named functions force you to do things the other way around. Decorator
> abuse is also a problematic approach, since even though it gets the
> order right, you end up with something that looks like an ordinary
> function or class definition but is actually nothing of the sort.
>
> Oh, I'll also note that the class variant gives you the full power of
> PEP 3150 without any (especially) funky new namespace semantics:
>
> :x = property(@.get, @.set, @.delete)
> class scope:
> def get(self):
> return __class__.attr
> def set(self, val):
> __class__.attr = val
> def delete(self):
> del __class__.attr
>
> Cheers,
> Nick.
>
> --
> Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
>
More information about the Python-ideas
mailing list