[Python-ideas] PEP 572: Statement-Local Name Bindings

Stephan Houben stephanh42 at gmail.com
Fri Mar 2 09:25:13 EST 2018


Hi all,

I would like to observe that there is already a way to bind names in an
expression:

a = (lambda b: [b, b])(b=f())

Currently this is not so performant, but there is nothing
stopping the compiler from special-casing such an
IIFE (Immediate Invoked Function Expression),
to use the Javascript terminology.

It would then be fast in, say, Python 3.8, but still work in earlier
versions.

Stephan



2018-03-02 14:26 GMT+01:00 Paul Moore <p.f.moore at gmail.com>:

> On 2 March 2018 at 12:48, Nick Coghlan <ncoghlan at gmail.com> wrote:
> > The design intent related rationale stems from the fact that closed over
> > references can live for an arbitrarily long time (as can regular function
> > locals in a generator or coroutine), and I think statement locals should
> be
> > as reliably ephemeral as we can reasonably make them if they're going to
> be
> > different enough from function locals to be worth the hassle of adding
> them.
> >
> > So that means asking a bunch of questions and deliberately giving the
> > *opposite* answer for statement locals than I would for function locals:
> >
> > * Visible in locals()? Yes for function locals, no for statement locals
> > * Visible in frame.f_locals? Yes for function locals, no for statement
> > locals
> > * Prevents access to the same name in outer scopes? Yes for function
> locals,
> > no for statement locals
> > * Can be closed over? Yes for function locals, no for statement locals
> >
> > Answer "no" to all those questions is only reasonable if statement local
> > references *look* different from regular variable names. But I also
> think we
> > need to proposing answering "No" to all of them to make statement locals
> > potentially interesting enough to be worth considering.
>
> OK, that argument makes sense to me. At least in the sense that it
> makes a good case for how statement-local names should work *if* we
> adopt them. I reserve the right to change my mind, as I haven't
> thought this through fully, but at least superficially I'm with you
> this far.
>
> I will note that I don't see this as a compelling reason for *having*
> them, just a good analysis of how they might behave if we do.
>
> > Neither PEP 527 nor 3150 *needs* the syntactic markers - the compiler can
> > figure out what is going on because it does the symbol table analysis
> pass
> > before the code generation pass, and hence can tag names appropriately
> based
> > on what it finds.
> >
> > My concern is for people reading the code, where omitting a syntactic
> marker
> > also forces *humans* to read things in two passes to make sure they
> > understand them correctly. Consider this example:
> >
> >     x = 10
> >     data = [x*x for i in range(10)]
> >
> > This will give you a 10 item list, where each item is 100.
> >
> > But now consider a world with statement locals, where statement locals
> use
> > the same reference syntax as regular locals:
> >
> >     x = 10
> >     data = [x*x for i in range(10) if (12 as x)]
> >
> > That's a deliberately pathological example (and you can already write
> > something similarly misleading using the "for x in [12]" trick), but the
> > fact remains that we allow out of order evaluation in expressions in a
> way
> > that we don't permit for statements.
>
> OK. That's my concern as well. But my conclusion is different - I view
> this as a pretty strong argument that the complexity cost is too high
> to justify the feature, rather than as a difficulty we need to
> mitigate in order to make the feature usable.
>
> > With a syntactic marker though, there's typically going to be less
> ambiguity
> > about where a name comes from:
> >
> >     x = 10
> >     data = [.x*.x for i in range(10) if (12 as .x)]
> >
> > It's not a panacea (since you may still be shadowing a name from an outer
> > statement), and adapting it for PEP 3150 isn't without it's problems
> > (specifically, you need to allow ".x = 12" in the given clause to make
> the
> > names match up), but it should be less confusing than allowing a new
> > subexpression to interfere with name resolution semantics folks have been
> > relying on for years.
>
> On my screen right now, I can barely see the dots. That's in email
> with a proportional font, so not "real coding", but it's surprising
> (and somewhat depressing :-() to think that probably the majority of
> code I read these days is in emails.
>
> So I don't think that this is a good enough fix to warrant making
> Tim's screen look gritty.
>
> > If statement locals behave just like function locals, then there's no
> reason
> > to add them to the language in the first place - "(expr as name)" would
> just
> > become a confusing second way to spell "name = expr".
>
> Well, the whole reason this debate keeps coming up is because people
> keep finding places they want to type "name = expr" but they can't,
> because their context isn't a statement. We're basically trying to
> design a replacement for "name = expr" that can be used in an
> expression. And the status quo is "refactor your expression into
> multiple statements". Doing so isn't always ideal (and particularly
> grates on people coming from languages where assignments are
> expressions, like C/C++) but it is always possible.
>
> Adding "mustn't just be another way to spell name = expr" to the
> requirements is an extra requirement - and arguably one that
> contradicts the original requirement which was "find a way to allow
> name = expr in expressions".
>
> Designing a broader feature which solves the original problem is a
> good goal, but we need to take care not to introduce scope creep or
> over generalisation. In this case, IMO, we're not doing that (yet!)
> but we are hitting design problems which are orthogonal to the
> original requirement.
>
> > It's only potentially worthwhile if statement locals offer us something
> that
> > function locals don't, and the clearest potential candidate for that
> > differentiation is to provide a greater level of assurance regarding
> > locality of use than regular name binding operations do.
>
> I disagree. It's *still* potentially worthwhile if it just offers a
> clean resolution for people who want to name complex sub-parts of a
> comprehension. But the bar for "clean" in that case is higher, because
> the benefit is pretty limited. I don't think it reaches that higher
> bar, but I also am not sure that the benefits of the wider proposal
> are sufficient to warrant the amount of lowering of the bar that is
> needed. (That metaphor got way too strained. I hope it still made
> sense).
>
>
> >> I guess I remain -1 on the proposal, and nothing that's getting said
> >> about how we can make it work is doing anything to persuade me
> >> otherwise (quite the opposite).
> >
> > Yep, that's fair, as there are *lots* of viable alternatives to inline
> > naming of subexpressions (each with various trade-offs). The question at
> > hand is whether we can come up with semantics and syntax that folks
> actually
> > like well enough to put to python-dev for a yes/no decision, with the
> pros
> > and cons consolidated in one place.
>
> Precisely.
>
> And the usual proviso that "status quo wins" applies strongly here,
> where (as noted in Chris' PEP) there are already *many* existing
> solutions.
>
> Paul
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180302/7830387b/attachment-0001.html>


More information about the Python-ideas mailing list