I would definitely love that kind of subscoping syntax, but as you say, that would be a much larger change. :)

The use of this for things like '2+2' would be, as you say, syntactic sugar; the compiler could even be clever and strip it out of the bytecode entirely. Its only purpose in that context would be to clarify place of use, and to allow simplification of multi-element 'with' assignments like in the last example I gave in the original email.

The principal purpose of this change, however, would be to enable things like optional value returns, in which in at least one fork of a conditional the 'with' statement would remain nontrivial.

On Sat, May 18, 2019 at 7:02 PM Chris Angelico <rosuav@gmail.com> wrote:
On Sun, May 19, 2019 at 11:46 AM David Mertz <mertz@gnosis.cx> wrote:
>>
>> I think you probably mean something other than what you actually write.  It doesn't really make sense for "any expression" as far as I can tell.  What would it possibly mean to write:
>>
>> with (2+2) as foo:
>>     print(foo)
>
>
> I have occasionally thought it would be nice to do something like this (and I could, but I haven't, so I guess I don't think it that strongly):
>
> >>> @contextmanager
> ... def bind(val):
> ...     yield val
> ...
> >>> with bind(2+2) as four:
> ...     print(four)
> ...
> 4
>

Thing is, this is slightly deceptive. People will assume/expect that
the name binding 'four' ends at the end of the 'with' block. In actual
fact, something like this has an entrance but no exit - there is
absolutely no meaning to the unindent. Functionality would be
identical to "with bind(2+2) as four: pass" followed by the same code.

Python's 'with' block guards a section of code. At the end of that
code, something has to get undone - a file gets closed, a database
transaction gets committed/rolled back, a suppressed exception returns
to normal state, etc. You can't have the __exit__ method do "del
four", so with current code, there's no code-significant meaning to
this block.

So there are two broad options:

1) Keep it having no functional meaning, just a semantic declaration
"hey, this is the only place I'm using this". Not hugely valuable, but
maybe people would like it. Probably best to have the three-line
bind() function.

2) Redefine the 'with' block or create a new syntactic form such that
the variable actually creates a subscope. That way, at the end of the
block, the name would revert to its former meaning.

x = 1
with local 2 as x:
    print(x) # 2
print(x) # 1

This would have definite value, but would be a much larger change to
the language. And variants of it have been proposed and rejected
before.

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/