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/