From: geremy condra on
On Sun, Jul 11, 2010 at 11:39 PM, Carl M. Johnson
<cmjohnson.mailinglist(a)gmail.com> wrote:
> On Sun, Jun 27, 2010 at 8:25 PM, Nick Coghlan <ncoghlan(a)gmail.com> wrote:
>
>> The availability of "nonlocal" binding semantics also makes the
>> semantics much easier to define than they were in those previous
>> discussions (the lack of clear semantics for name binding statements
>> with an attached local namespace was the major factor blocking
>> creation of a reference implementation for this proposal back then).
>>
>> For example:
>>
>>  c = sqrt(a*a + b*b) where:
>>    a = retrieve_a()
>>    b = retrieve_b()
>>
>> could translate to something like:
>>
>>  def _anon(): # *(see below)
>>    nonlocal c
>>    a = retrieve_a()
>>    b = retrieve_b()
>>    c = sqrt(a*a + b*b)
>>  _anon()
>>
>> *(unlike Python code, the compiler can make truly anonymous functions
>> by storing them solely on the VM stack. It already does this when
>> executing class definitions):
>
> I like this idea, but I would tweak it slightly. Maybe we should say
>
> EXPRESSION where:
>    BLOCK
>
> is equivalent to
>
> def _():
>    BLOCK
>    return EXPRESSION
> _()
>
> That way, c = a where: a = 7 would be equivalent to
>
> def _():
>   a = 7
>   return a
> c = _()
>
> One advantage of this equivalence is it would make it easier to work
> around a longstanding scoping gotcha. A naïve coder might expect this
> code to print out numbers 0 to 4:
>
>    >>> fs = []
>    >>> for n in range(5):
>    ...     def f():
>    ...         print(item)
>    ...     fs.append(f)
>    ...
>    >>> [f() for f in fs]
>    4
>    4
>    4
>    4
>    4
>    [None, None, None, None, None]
>
> I think we all have enough experience to know this isn’t a totally
> unrealistic scenario. I personally stumbled into when I was trying to
> create a class by looping through a set of method names.
>
> To get around it, one could use a where clause like so:
>
> fs = []
> for n in range(5):
>    fs.append(f) where:
>        shadow = n
>        def f():
>            print(shadow)
>
> This would print out 0 to 4 as expected and be equivalent to
>
>    >>> fs = []
>    >>> for n in range(5):
>    ...     def _():
>    ...         shadow = n
>    ...         def f():
>    ...             print(shadow)
>    ...         fs.append(f)
>    ...     _()
>    ...
>    >>> [f() for f in fs]
>    0
>    1
>    2
>    3
>    4
>    [None, None, None, None, None]
>
> I think a where-clause with def-like namespace semantics would be a
> positive addition to Python, once the moratorium is up.
>
> -- Carl Johnson

+1 from me, FWIW

Geremy Condra