On 27Nov2020 21:13, Steven D'Aprano <st...@pearwood.info> wrote:
>On Fri, Nov 27, 2020 at 08:32:04AM +1100, Cameron Simpson wrote:
>> On 27Nov2020 00:25, Steven D'Aprano <st...@pearwood.info> wrote:
>> >Block scoping allows shadowing within a function.
>>
>> Just to this: it needn't.
>
>Yes, I'm aware of that, and discussed languages such as Java which
>prohibit name shadowing within a function.
>https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.4
>
>Shadowing is a double-edged sword. It is sometimes useful, but often a
>source of hard to find bugs. One might argue that a language should
>allow *some* shadowing but not too much.

"mm, yeah. I'd think I'd be happier simply disallowing it.

Got a nice example of somewhere where shadowing would be useful and hard 
to do some task otherwise?

>> You could forbid shadowing of the _static_ outer scope easily enough 
>> at
>> parse/compile time. That would prevent a certain class of easy misuse.
>>
>>     i = 9
>>     { new scope here for "i" ==> parse/compile error, since "i" is in
>>     play
>>     }
>
>Yes, that's precisely the sort of thing I discussed, and described as
>action-at-a-distance between two scopes, where the mere existence of a
>name in scope A prevents you from using the same name in scope B.

Well, it prevents a lot of easy mistakes. I think for it to be "action 
at a distance" the function / code block would need to be quite long.  
Generally held to be a poor practice (not that I haven't some quite long 
functions of my own, of course, but I accept the cognitive burden there 
for other reasons).

>The problem is, if your inner block scope must not reuse variable names
>in the outer function scope, well, what's the advantage to making them
>seperate scopes?

Lifetime, but in terms of referencing resources and also accidental 
(mis)use of something beyond where it was supposed to be used. I used to 
do short {...} scopes in C all the time for this purpose.

>Analogy: I think most of us would consider it *really weird* if this
>code was prohibited:
>
>    a = None
>
>    def func():
>        a = 1  # Local with the same name as the global prohibited.

Yes, but a function is a clean new scope to my mind. (Yes, closures.) As 
opposed to this:

    f = None

    # define a lifespan for "f" using the fictitious "as new" syntax.
    with open("foo") as new f:
        process file f

    # f is None again

I'd be all for forbidding that, and instead requiring a different name 
for the with-statement "f".

>One possible advantage, I guess, is that if your language only runs the
>garbage collector when leaving a scope, adding extra scopes helps to
>encourage the timely collection of garbage. I don't think that's a big
>advantage to CPython with it's reference counting gc.

I'm not concerned directly with garbage collection so much as preventing 
use of a name beyond its intended range. Which is the next bit:

>> That said, there _are_ times I wish I could mark out the lifetime of 
>> a
>> variable, akin to C level:
>>
>>     ... i does not exist ...
>>     { int i;
>>       ... use i ...
>>     }
>>     ... i now unknown, use is an error ...
>>
>> The nearest Python equivalent is:
>>
>>     i = blah()
>>     ... use i
>>     del i
>>
>> which feels fragile - accidental assignment to "i" later is not
>> forbidden.
>
>Why do you care about the *name* "i" rather than whatever value is bound

Because of intent. Why do we encapsulate things in functions? It isn't 
just releasing resources and having convenient code reuse, but also to 
say "all these names inside the function are only relevant to it, and 
are _not_ of use after the function completes".

>I completely get the idea of caring about the lifetime of an object,
>e.g. I understand the need to garbage collect the exception object when
>leaving `except` blocks. (At least by default.)
>
>But I don't get why I might care about the lifetime of a *name*.

Maybe not. But I very much do.

>    try:
>        ...
>    except Exception as e:
>        pass
>    e  # Name is unbound, for good reasons.
>    e = None  # But why should this be an error?
>
>
>We don't generally take the position that reuse of a name in the same
>function is Considered Harmful, let alone *so harmful* that we need the
>compiler to protect us from doing so.

Indeed not.

But Sometimes I _want_ do take that position, for _particular_ names.

>If I am *accidentally* reusing names, my code has much bigger
>problems than just the name re-use:
>- my names are so generic and undescriptive that that can be re-used 
>for unrelated purposes;

Wasn't one of your complaints above "Why do you care about the *name* 
"i" rather than whatever value is bound"? "i" is a _very_ generic and 
undescriptive name.

>- and the function is so large and/or complicated that I don't notice
>when I am re-using a name.

>Name re-use in the bad sense is a symptom of poor code, not a cause of
>it, and as such block scopes are covering up the problem.
>
>(That's my opinionated opinion :-)

Aye. I think we may need to just disagree here. I think we agree that 
name "misreuse" is symptomatic of larger problems. But we seem to 
disagree about letting the compiler _aid_ us in defining the intended 
bounds of use, so that the compiler can be _told_ of the range, and warn 
us (or the coder who comes afterward) about this error.

The more I _can_ say about names and their use, the better. How _much_ I 
then say is a matter of requirements, style and taste.

Do you use linters? I do. And the very neat typeguard module which can 
check type annotations at runtime, and icontract which can vet 
preconditions and post conditions at runtime, etc.

Cheers,
Cameron Simpson <c...@cskk.id.au>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3IKFBQ5NZ2X7RARMMJORM4V7GSVV5IQG/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to