On Wed May 16 20:53:46 EDT 2018, Steven D'Aprano wrote:
> On Wed, May 16, 2018 at 07:24:19PM +0200, Adam Bartoš wrote:
>> Hello,
>> I have yet another idea regarding the the clashes between new keywords and
>> already used names. How about introducing two new keywords *wink* that
>> would serve as lexical keyword/nonkeyword declarations, similarly to
>> nonlocal and global declarations?
>> def f():
>>     nonkeyword if
>>     if = 2 # we use 'if' as an identifier
>>     def g():
>>         keyword if
>>         if x > 0: pass # now 'if' again introduces a conditional statement
> This is absolutely no help at all for the common case that we have an
> identifier that is a keyword and want to use it as a keyword in the same
> block. For example, we can currently write:
>     try:
>        value = data.except_
>     except:
>         value = data.missing()
> say. We're using "except_" because the data comes from some external
> interface where it uses "except", but we can't use that because its a
> keyword.

If it was possible to consider any syntactical block for the declarations, this use case could be handled like:

    nonkeyword except
    value = data.except
    value = data.missing()

Alternatively, data.except could be allowed even without a declaration as another idea suggests. There are syntactical positions where it is easy to distinguish between a keyword and an identifier, there are positions where it is harder, or even impossible due to limitations on the parser complexity. So both ideas may be viewed as complementary, and the base case of my proposal would be just a per module opt out from a keyword, so it is easier to fix such module when a new keyword is introduced in the language.

> I also challenge to think about how you will document the complicated
> rules for when you can and can't use keywords as names, especially think
> about explaining them to beginners:
>     def spam(None=42):
>         print(None)  # What will this print?
>         x = None  # Fine, but what does it do?
>         None = 999  # Is this an error or not?

None is a different kind of keyword. Ordinary keywords that make the statements of the language have no value, so 'x = if' makes no sense. On the other hand, None, True, and False are singleton values (like Ellispsis and NotImplemented) that are additionally protected from be redefined, which makes them similar to keywords. I think that the barrier for adding new keyword constants is even higher than the barrier for adding new ordinary keywords, and so may be omited when trying to solve the keyword/identifier problem.

nonkeyword None # SyntaxError: a keyword constant 'None' cannot be an identifier

> Remember the KISS principle.

It seemed to me that the syntactical block based declarations are quite simple in principle, but you are right, there are many issues.

Best regards,
Adam Bartoš