On Sun, Nov 29, 2020 at 12:10:39AM +0300, Paul Sokolovsky wrote:

> And we don't speak about some obscure "innovative" idea. Const'ness
> aka immutability is well-known and widely used feature in programming
> languages.

Constantness and immutability are not synonyms.

Immutability refers to *objects*. "abc" is an immutable object; `[]` is 
not, it is mutable.

Constantness refers to *name bindings*: once the name is bound to an 
object, it cannot be re-bound to a different object.

So you can have:

- variables bound to a mutable object;
- variables bound to an immutable object;
- constants bound to a mutable object;
- constants bound to an immutable object.

and you could have the same object bound to multiple names, some of 
which could be variables and some constants.

A mutable constant could still be mutated:

    const spam = []
    spam.append(None)  # Allowed.

but not rebound:

    spam = [1, 2]  # Forbidden.

> So, let's go over it again. You probably say that C uses following
> syntax to define a variable in a particular scope:
> <type> <var>;
> e.g.:
> int var;
> Right, Python doesn't have that syntax. But it has other syntaxes to
> designate that a variable is defined in a particular scope:
> # e is defined in the scope of the following block
> except Exception as e:  

That is incorrect. e is defined in the *current* scope. There is no 
"scope of the following block".

Exception blocks are a special case, because there is dedicated code to 
unbind (delete) the "e" name when the block is left. But the name is 
local to the current scope, the block does not create a new scope.

That same applies to all other blocks.

> # x is defined in the scope of a comprehension
> [x for x in seq]
> Then for pattern matching,
> case a, b:
> *Could* define a, b in the scope of following block (and not beyond).
> That would have pros and cons, an obvious pro is that failing-to-match
> patterns would not litter in surrounding namespace, and con that
> "pattern matching as expression" usage would be more harder. If
> anything, use of block scoping could be considered to alleviate the
> littering problem

The "littering problem" will be a non-problem in practice.

> Let's strive for solutions which follow the best practices in the
> programming language design (const'ness, block-level scoping are 2
> good examples), 

There isn't even a single definition for block-scoping. C block scoping 
and Java block scoping are not the same. So which one is best practice?

At *best* it is a matter of personal taste whether you like or dislike 
block scoping, but I'm going to stick my head out and say that it is an 
unnecessary complication that will cause more annoyance and confusion in 
Python than benefit.

> "Undefined behavior" regarding how failed matches may affect
> surrounding namespace is unlikely something to be proud of.

We should not use the term *undefined behaviour* because that carries 
too much baggage from C, where undefined behaviour is a truly 
frightening thing.

In Python, it just means implementation defined. We have lots of 
implementation defined behaviour:

- caching of small ints and strings;

- whether changes to locals() effects local variables;

- performance of string concatenation;

- many floating point operations, e.g. trig functions, powers;

- presence or absense of many platform-dependent features;

- (in the past) Unicode narrow or wide builds;

- details of precisely when objects will be garbage collected;

- iteration order of sets;

and I expect there are others.

Let us be clear: failed matches do not affect *surrounding* namespaces 
unless you declare capture variables as global or nonglobal. They 
*might* affect the current namespace, but not surrounding namespaces. 
Failed matches will not leak out to surrounding namespaces.

Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
Message archived at 
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to