On Tue, May 25, 2021 at 5:29 PM Steven D'Aprano <st...@pearwood.info> wrote:
> Here's a counter-proposal: we have a special symbol which is transformed
> at compile-time to the left hand assignment target as a string. Let's
> say we make that special expression `@@` or the googly-eyes symbol.

This is sounding promising. I'm liking this.

> Then:
>
>     RED = @@
>     # transforms to `RED = 'RED'`
>
>     GREEN = "dark " + @@.lower()
>     # transforms to `GREEN = "dark " + 'GREEN'.lower()`
>
>     myclass = type(@@, bases, namespace)
>     # transforms to `myclass = type('myclass', bases, namespace)`
>
>     # Not all functions expect the name as first argument.
>     result = function(arg, value, @@)
>     # transforms to `result = function(arg, value, 'result')`

Decent.

> If there's no target, it resolves to None:
>
>     print(@@)  # print(None)
>
> or if people prefer a SyntaxError, I'm okay with that too.

Bikesheddable. I'd be inclined to go with SyntaxError, and make @@ a
syntactic construct that is inherently part of the assignment; that
way, there's no confusion in other contexts. No big deal either way.

> Targets aren't limited to a single bare name.
>
>     spam.eggs = @@
>     # spam.eggs = 'spam.eggs'
>
>     mylist[2] = @@
>     # mylist[2] = 'mylist[2]'

What about:

mylist[ 2 ] = @@

? I'm inclined to say that the assignment target is reconstructed from
the AST, in order to make it consistent (so this would also assign the
string 'mylist[2]'). But, again, bikesheddable.

> If the key or index is not known at compile-time, it is a syntax error:
>
>     mylist[getindex()] = @@  # SyntaxError

Also bikesheddable; I'd actually say that this should assign the
string 'mylist[getindex()]', regardless of the value returned by
getindex.

> Chained assignments transform to a tuple of target names:
>
>    spam = eggs = cheese = func(arg, @@)
>    # spam = eggs = cheese = func(arg, ('spam', 'eggs', 'cheese'))

Hmm. Everything else gives you a single string, this one doesn't. I'd
actually be inclined to switch around this one and the next one...

> Sequence unpacking assignment gets transformed as a single
> comma-seperated string:
>
>     spam.eggs, foo, *bar = func(arg, @@)
>     # spam.eggs, foo, *bar = func(arg, ('spam.eggs,foo,*bar'))

... so that assigning the same thing to multiple names gives you a
space-separated string (or equals-separated, "spam=eggs=cheese"), but
unpacking gives you a tuple of targets, since it then nicely parallels
the result it's expecting from the function. That would mean that:

# This assigns a single string to them all eg "spam eggs cheese"
spam = eggs = cheese = @@
# This assigns a string to each one:
spam, eggs, cheese = @@
# and is equivalent to:
spam = @@; eggs = @@; cheese = @@

> Target resolution is performed at compile-time, not runtime. There's no
> global variable called "@@". That means that this won't work:
>
>     code = compile("type(@@, bases, namespaces)", '', 'single')
>     # above transforms to `type(None, bases, namespace)`
>     myclass = eval(code)
>
> But I think that restriction is fine.
>

Absolutely.

This has the same sort of value as the C preprocessor stringification
operator. It's incredibly handy in making self-referential statements.
Python has places where that happens by magic (class and function
definitions), but if you want to create your own function that gets
the same benefit.... well.... there's __set_name__ if your thing gets
put into a class, but otherwise you have to repeat the name.

Questions:

1) Is this restricted to the "=" assignment operator, or will other
operators trigger this too?
x += f(@@) # ?
if x := f(@@): # ?

2) What about other forms of assignment?
for spam in foo(@@): # ?
with open(@@ + ".json") as config: # ?
from sys import @@ as argv # okay that's just stupid

3) Is this a string literal, or a magic token that happens to evaluate
as a string?
x = @@ ".json" # Legal if @@ is a string literal

No wrong answers. (Well, unless you say "tomato". That is a very wrong
answer to a yes/no question.)

I'm liking this. It might mean that class syntax and decorator abuse
become less necessary as ways to get around name duplication.

ChrisA
_______________________________________________
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/N2FADF5MRBFCU3EO7EZA7PWXKF54HACX/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to