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