Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-30 Thread Chris Angelico
On Mon, Apr 30, 2018 at 6:20 PM, Matt Arcidy  wrote:
> Does this mean indentation is now a scope, or colons are a scope, or is that
> over simplifying?

No, no, and yes. This is JUST about the 'except' statement, which
currently has the weird effect of unbinding the name it just bound.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-30 Thread Matt Arcidy
On Sat, Apr 28, 2018, 20:16 Chris Angelico  wrote:

> There's been a lot of talk about sublocal scopes, within and without
> the context of PEP 572. I'd like to propose what I believe is the
> simplest form of sublocal scopes, and use it to simplify one specific
> special case in Python.
>
> There are no syntactic changes, and only a very slight semantic change.
>
> def f():
> e = 2.71828
> try:
> 1/0
> except Exception as e:
> print(e)
> print(e)
> f()
>
> The current behaviour of the 'except... as' statement is as follows:
>
> 1) Bind the caught exception to the name 'e', replacing 2.71828
> 2) Execute the suite (printing "Division by zero")
> 3) Set e to None
> 4) Unbind e
>
> Consequently, the final print call raises UnboundLocalError. I propose
> to change the semantics as follows:
>
> 1) Bind the caught exception to a sublocal 'e'
> 2) Execute the suite, with the reference to 'e' seeing the sublocal
> 3) Set the sublocal e to None
> 4) Unbind the sublocal e
>
> At the unindent, the sublocal name will vanish, and the original 'e'
> will reappear. Thus the final print will display 2.71828, just as it
> would if no exception had been raised.
>
>
Does this mean indentation is now a scope, or colons are a scope, or is
that over simplifying?

either seems to be more consistent with the patterns set by class and
function defs, barring keywords.

not sure if relevant but curious.

I think with sublocal scope, reuse of a name makes more sense.  Currently,
if using sensible, descriptive names, it really doesn't make sense to go
from food = apple to food = car as the value between scopes, but it
happens.  And if from fruit = apple to fruit = orange (eg appending a msg
to a base string) it _could_ be nice to restore to apple once finished.

Obviously that's simple enough to do now, I am only illustrating my point.
I know bad code can be written with anything, this is not my point.  It can
be seen as enforcing that, what every nonsense someone writes like
fruit=car, there is at least some continuity of information represented by
the name... till they do it again once out of the sublocal scope of course.

as for the value of this use case, I do not know.


> The above definitions would become language-level specifications. For
> CPython specifically, my proposed implementation would be for the name
> 'e' to be renamed inside the block, creating a separate slot with the
> same name.
>
> With no debates about whether "expr as name" or "name := expr" or
> "local(name=expr)" is better, hopefully we can figure out whether
> sublocal scopes are themselves a useful feature :)
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-29 Thread Greg Ewing

Chris Angelico wrote:

1) Bind the caught exception to a sublocal 'e'
2) Execute the suite, with the reference to 'e' seeing the sublocal
3) Set the sublocal e to None
4) Unbind the sublocal e

At the unindent, the sublocal name will vanish, and the original 'e'
will reappear.


That's a reasonable way to define how a sublocal scope
might work. But as far as I can see, the debate is about
whether sublocal scopes are a good idea in the first
place.

--
Greg

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-29 Thread Nick Coghlan
On 29 April 2018 at 21:24, Chris Angelico  wrote:

> On Sun, Apr 29, 2018 at 6:03 PM, Nick Coghlan  wrote:
> > The challenge with doing this implicitly is that there's no indication
> > whatsoever that the two "e"'s are different, especially given the
> > longstanding precedent that the try/except level one will overwrite any
> > existing reference in the local namespace.
>
> My intention is that the "except" statement IS the indication that
> they're different. Now that the name gets unbound at the exit of the
> clause, the only indication that it overwrites is that, after "except
> Exception as e:", any previous e has been disposed of. I'd hardly call
> that a feature. Can you show me code that actually DEPENDS on this
> behaviour?
>

That's not the bar the proposal needs to meet, though: it needs to meet the
bar of being *better* than the status quo of injecting an implicit "del e"
at the end of the suite.

While the status quo isn't always convenient, it has two main virtues:

1. It's easily explained in terms of the equivalent "del" statement
2. Given that equivalence, it's straightforward to avoid the unwanted side
effects by either adjusting your exact choices of names (if you want to
avoid overwriting an existing name), or else by rebinding the caught
exception to a different name (if you want to avoid the exception reference
getting dropped).

I do agree that *if* sublocal scopes existed, *then* they would offer a
reasonable implementation mechanism for block-scoped name binding in
exception handlers. However, exception handlers don't offer a good
motivation for *adding* sublocal scopes, simply because the simpler
"implicitly unbind the name at the end of the block" approach works well
enough in practice.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-29 Thread Chris Angelico
On Sun, Apr 29, 2018 at 6:03 PM, Nick Coghlan  wrote:
> The challenge with doing this implicitly is that there's no indication
> whatsoever that the two "e"'s are different, especially given the
> longstanding precedent that the try/except level one will overwrite any
> existing reference in the local namespace.

My intention is that the "except" statement IS the indication that
they're different. Now that the name gets unbound at the exit of the
clause, the only indication that it overwrites is that, after "except
Exception as e:", any previous e has been disposed of. I'd hardly call
that a feature. Can you show me code that actually DEPENDS on this
behaviour?

> By contrast, if the sublocal marker could be put on the *name itself*, then:
>
> 1. Sublocal names are kept clearly distinct from ordinary names
> 2. Appropriate sublocal semantics can be defined for any name binding
> operation, not just exception handlers
> 3. When looking up a sublocal for code compiled in exec or eval mode,
> missing names can be identified and reported at compile time (just as they
> can be for nonlocal declarations) (Such a check likely wouldn't be possible
> for code compiled in "single" mode, although working out a suitable
> relationship between sublocal scoping and the interactive prompt is likely
> to prove tricky no matter what)

I'm aware of this, but that gets us right back to debating syntax, and
I'm pretty sure death and syntaxes are the two things that we can
truly debate forever. :)

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-29 Thread Nick Coghlan
On 29 April 2018 at 13:14, Chris Angelico  wrote:

> There's been a lot of talk about sublocal scopes, within and without
> the context of PEP 572. I'd like to propose what I believe is the
> simplest form of sublocal scopes, and use it to simplify one specific
> special case in Python.
>
> There are no syntactic changes, and only a very slight semantic change.
>
> def f():
> e = 2.71828
> try:
> 1/0
> except Exception as e:
> print(e)
> print(e)
> f()
>
> The current behaviour of the 'except... as' statement is as follows:
>
> 1) Bind the caught exception to the name 'e', replacing 2.71828
> 2) Execute the suite (printing "Division by zero")
> 3) Set e to None
> 4) Unbind e
>
> Consequently, the final print call raises UnboundLocalError. I propose
> to change the semantics as follows:
>
> 1) Bind the caught exception to a sublocal 'e'
> 2) Execute the suite, with the reference to 'e' seeing the sublocal
> 3) Set the sublocal e to None
> 4) Unbind the sublocal e
>
> At the unindent, the sublocal name will vanish, and the original 'e'
> will reappear. Thus the final print will display 2.71828, just as it
> would if no exception had been raised.
>

The challenge with doing this implicitly is that there's no indication
whatsoever that the two "e"'s are different, especially given the
longstanding precedent that the try/except level one will overwrite any
existing reference in the local namespace.

By contrast, if the sublocal marker could be put on the *name itself*, then:

1. Sublocal names are kept clearly distinct from ordinary names
2. Appropriate sublocal semantics can be defined for any name binding
operation, not just exception handlers
3. When looking up a sublocal for code compiled in exec or eval mode,
missing names can be identified and reported at compile time (just as they
can be for nonlocal declarations) (Such a check likely wouldn't be possible
for code compiled in "single" mode, although working out a suitable
relationship between sublocal scoping and the interactive prompt is likely
to prove tricky no matter what)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Sublocal scoping at its simplest

2018-04-28 Thread Steven D'Aprano
On Sun, Apr 29, 2018 at 01:14:54PM +1000, Chris Angelico wrote:

[...]
> def f():
> e = 2.71828
> try:
> 1/0
> except Exception as e:
> print(e)
> print(e)
> f()


> I propose to change the semantics as follows:
> 
> 1) Bind the caught exception to a sublocal 'e'
> 2) Execute the suite, with the reference to 'e' seeing the sublocal
> 3) Set the sublocal e to None
> 4) Unbind the sublocal e
> 
> At the unindent, the sublocal name will vanish, and the original 'e'
> will reappear. Thus the final print will display 2.71828, just as it
> would if no exception had been raised.

What problem does this solve?

The current behaviour where 'e' is unbound when the except clause 
finishes is a neccessary but ugly hack that forces you to do bind 'e' to 
another variable if you want to inspect it after the exception:

try:
something()
except Exception as e:
err = e  # defeat the automatic deletion of e
print(e)

For example, in the interactive interpreter, where I do this very 
frequently.

I understand and accept the reasons for deleting e in Python 3, and 
don't wish to re-debate those. But regardless of whether we have 
Python 3 behaviour or Python 2 behaviour, binding to e has always 
replaced the value of e. Just as if I had written:

except Exception as some_other_name:
e = some_other_name

It has never been the case that binding to e in the except clause won't 
replace any existing binding to e, and I see no reason why anyone would 
desire that. If you don't want to replace e, then don't use e as the 
name for the exception.

Your proposal doesn't solve any known problem that I can see. For people 
like me who want to inspect the error object outside the except clause, 
we still have to defeat the compiler, so you're not solving anything for 
me. You're not solving any problems for those people who desire (for 
some reason) that except clauses are their own scope. It is only the 
exception variable itself which is treated as a special case.

The one use-case you give is awfully dubious: if I wanted 'e' to keep 
its value from before the exception, why on earth would I rebind 'e' 
when there are approximately a zillion alternative names I could use?

Opportunities for confusion should be obvious:

e = 2.71
x = 1
try:
...
except Exception as e:
assert isinstance(e, Exception)
x = 2
assert isinstance(e, Exception)  # why does this fail?
assert x != 2  # why does this fail?

Conceptually, this is even more more complex than the idea of giving the 
except block its own scope. The block shares the local scope, it's just 
the block header (the except ... as ... line itself) which introduces a 
new scope.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Sublocal scoping at its simplest

2018-04-28 Thread Chris Angelico
There's been a lot of talk about sublocal scopes, within and without
the context of PEP 572. I'd like to propose what I believe is the
simplest form of sublocal scopes, and use it to simplify one specific
special case in Python.

There are no syntactic changes, and only a very slight semantic change.

def f():
e = 2.71828
try:
1/0
except Exception as e:
print(e)
print(e)
f()

The current behaviour of the 'except... as' statement is as follows:

1) Bind the caught exception to the name 'e', replacing 2.71828
2) Execute the suite (printing "Division by zero")
3) Set e to None
4) Unbind e

Consequently, the final print call raises UnboundLocalError. I propose
to change the semantics as follows:

1) Bind the caught exception to a sublocal 'e'
2) Execute the suite, with the reference to 'e' seeing the sublocal
3) Set the sublocal e to None
4) Unbind the sublocal e

At the unindent, the sublocal name will vanish, and the original 'e'
will reappear. Thus the final print will display 2.71828, just as it
would if no exception had been raised.

The above definitions would become language-level specifications. For
CPython specifically, my proposed implementation would be for the name
'e' to be renamed inside the block, creating a separate slot with the
same name.

With no debates about whether "expr as name" or "name := expr" or
"local(name=expr)" is better, hopefully we can figure out whether
sublocal scopes are themselves a useful feature :)

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/