On Tue, May 25, 2021 at 5:29 PM Steven D'Aprano <[email protected]> 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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/[email protected]/message/N2FADF5MRBFCU3EO7EZA7PWXKF54HACX/
Code of Conduct: http://python.org/psf/codeofconduct/