On 13May2018 08:55, Chris Angelico <ros...@gmail.com> wrote:
On Sun, May 13, 2018 at 8:47 AM, Juancarlo Añez <apal...@gmail.com> wrote:
My main point here is that "with" works as well as "given" in this form
from an English prose point of view.
+1 for "with...as", -1 for ":="
About affecting existing contexts, it seems that "with..as" would create a
new context just for the expression, and the control statement it is
embedded in, similar to what the current "with" statement does. These are
semantics that are really easy to explain.
The trouble with every variant involving 'with' is that the semantics
LOOK similar, but are subtly different. The current 'with' statement
doesn't create a subscope; the only "context" it creates is regarding
the resource represented by the context manager. For instance, opening
a file in a 'with' block will close the file at the end of the block -
but you still have a (closed) file object. Using "with... as" for name
bindings wouldn't call __enter__ or __exit__, so it won't create that
kind of context; and whether it creates a subscope for the variable or
not, it's not going to match the 'with' statement.
For myself, I'm not a fan of a narrow scope. I'd be happy with an inline
assignment landing in the function scope (or whatever the current innermost
scope is). Like normal assignments. In how many other places does Python adopt
a narrower scope than the function/method/class/module?
Consider:
r = re.compile("bah(baz)")
if m given m = r.match("foo barbaz"):
thing = m.group(1)
I _want_ to access "m" after the expression.
My other dislike of narrow scopes is shadowing. I had an unpleasant experience
last year working in Go, which has its own ":=" assignment. While Go's :=
semantics are a little different to the assignment expressions being considered
here, it has an IMO dangerous shadowing effect.
I'm going to digress into an explaination of this issue in Go here because I
want to highlight my dislike of easy accidental shadowing, which is a problem
in many areas, and I think that conflating inline assignment with an implied
narrow scope in Python would make this worse.
In Go you can declare variables 2 ways:
var ok = True
and:
ok := True
Also, because Go doesn't use exceptions a common idiom is to return a
success/fail value and the task's result:
ok, result := do_something(...)
That handily declares "ok" and "result" and gives them values.
Because the ":=" is so convenient, you might often declare variables as they
get used:
ok, result1 := do_something()
ok, result2 := do_something_else()
and so on. You're allowed to mix existing names with new (undeclared) names
provided there's at least one new name left of the ":=".
So far this is all just ordinary assignments, with convenient declaration
included. But consider the function that calls other functions:
func thing_outer(x) {
ok, result1 := do_something()
if ok {
ok, result2 := do_something_else()
if ok {
fmt.Println("ok!")
}
}
return ok, result
}
That's how it might go in Pythonic form. But Go lets you preceed the test
condition with a statement, somewhat like the C "for (setup values; test;
advance)" form:
for (i=0; i<10; i++)
So you may wish to write the function like this:
func thing_outer(x) {
if ok, result1 := do_something(); ok {
if ok, result2 := do_something_else(); ok {
fmt.Println("ok!")
}
}
return ok, result
}
and here is where the scoping causes a disaster.
In Go, the declarations _within_ the "if" statement have the "if" statement as
their scope. In particular, the inner "ok" shadows the outer "ok", such that an
inner failure (setting "ok" to false) doesn't affect the outer "ok" which was
true. And so the overall function returns apparent success.
And that is entirely enabled by the implied scoping in the "if" statement.
The above example is subtly wrong because I'm doing this from memory, but I had
a very simple real world example bite me this way and it was a PITA to debug
because the effect was so surprising. So much so that from then on I pretty
much eschewed the ":=" declaration as a dangerous construct and went with "var"
all the time, effectively giving me _one_ scope within any function.
Cheers,
Cameron Simpson <c...@cskk.id.au>
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/