On Tue, May 25, 2021 at 10:10:12PM +1000, Chris Angelico wrote:
> 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.

[...]
> > 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.

Let the implementation decide whether it is easier to get the target 
from the source code or the AST. I don't care either way.


> > 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.

My reasoning it that it is safer and more conservative to start with a 
restriction and relax it later, than to start with a less restrictive 
version and regret it.

But I could be persuaded otherwise :-)


> > 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...

A complication I just thought of is that you can have chained assignment 
within a 
sequence unpacking assignment:

    spam, eggs, aardvark = foo = bar, hovercraft = 'abcd'

and the other way around:

    spam = eggs = (aardvark, foo, bar) = hovercraft = 'abc'

That's going to make things tricky.


> > 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 = @@

I have to think about that some more :-)


> This has the same sort of value as the C preprocessor stringification
> operator. It's incredibly handy in making self-referential statements.

Nice analogy.

> 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.

Yes.

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

I hadn't thought that far ahead. I did think that we ought to exclude 
the walrus operator because it would be ambiguous:

    spam = eggs * (cheese:=foo+bar(@@))

Does @@ get the value 'cheese' or 'spam'? If we require an assignment 
statement, then it can only be 'spam' and the ambiguity is gone.


> 2) What about other forms of assignment?
> for spam in foo(@@): # ?

YAGNI.

We can always extend the functionality later. Let's keep it simple: it 
works for assignment statements, not every binding operation.


> 3) Is this a string literal, or a magic token that happens to evaluate
> as a string?

An actual string.


> x = @@ ".json" # Legal if @@ is a string literal

Heh, I wouldn't necessarily require that. (Nor would I object to it.) 
Implicit string concatenation is a nice feature, but I'm not sure we 
want to extend it. Its not hard to slot an explicit `+` in there.



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

Reply via email to