On Thu, Aug 27, 2020 at 09:57:26AM -0400, Ricky Teachey wrote:

> Sorry, I need to stop coding in shorthand.

That might help.

What might help even more is if you spend less time showing imaginary, 
and invariably buggy, examples and more time explaining in words the 
intended semantics of this, and the reason why you want those semantics.

I had to read over your email three times before the penny dropped what 
you are actually saying. Partly because I haven't had breakfast yet, 
partly because I was still thinking about earlier versions of your 
proposal e.g. when you had a single subscript dunder get passed the name 
of the get- set- or del-item dunder, and was expected to dispatch to 
that method. But mostly because your description is so full of fine 
detail that the big picture is missing.

So let me see if I have this. You want to add a special dunder method 
which, if it exists, is automatically called by the interpreter to 
preprocess the subscript before passing it to the usual get-, set- and 
del-item dunders.

So instead of having this:

    # hypothetical change to subscript behaviour
    # to allow multiple arguments
    def __getitem__(self, fee, fi, fo, fum):
        ...
    # and similar for __setitem__ and __delitem__


We will have this:

    def __subscript__(self, fee, fi, fo, fum):
        return (fee, fi, fo, fum, {})
    def __getitem__(self, fee, fi, fo, fum, **kw):
        assert kw == {}
        ...
    # and similar for __setitem__ and __delitem__


and the process changes from:

* interpreter passes arguments to the appropriate dunder

to this instead:

* interpreter passes arguments to the subscript dunder
* which preprocesses them and returns them
* and the interpreter then passes them to the appropriate dunder.

I'm underwhelmed.

I *think* your intention here is to handle the transition from the 
status quo to full function-like parameters in subscripts in a backwards 
compatible way, but that's not going to work.

The status quo is that the subscript is passed as either a single value, 
or a tuple, not multiple arguments. If that *parsing rule* remains in 
place, then these two calls are indistinguishable:

    obj[spam, eggs]
    obj[(spam, eggs)]

and your subscript dunder will only receive a single argument because 
that's what the parser sees. So you need to change the parser rule.

But that breaks code that doesn't include the subscript dunder, because 
now this:

    obj[spam, eggs]

gets passed as two args, not one, and `__getitem__` has only been 
written to accept one, so you get a TypeError.

Your subscript preprocessor would allow the coder to stick spam and eggs 
into a tuple and pass it on, but it also returns a dict so the getitem 
dunder still needs to be re-written to accept `**kwargs` and check that 
it's empty, so you're adding more, not less, work. And besides, if I 
have to add a brand new dunder method to my class in order for my item 
getter to not break, it's not really backwards-compatible.

Okay, let's make the interpreter smarter: it parses spam, eggs as two 
arguments, and then sees that there is no subscript dunder, so it drops 
back to "legacy mode", and assembles spam and eggs into a tuple before 
passing it on to the item getter.

Only that's not really backwards compatible either, because the 
interpreter can't distinguish the two cases:

    # single argument with trailing comma
    obj[spam,]

    # no trailing comma
    obj[spam]

In both cases this looks like a single argument to the interpreter, but 
the status quo is that they are different. The first one needs to be a 
tuple of one item.

Why add all this complexity only to fail to remain backwards-compatible? 
Better would be to add a new future directive to change the parsing of 
subscripts, and allow people to opt-in when they are ready on a 
per-module basis.

    from __future__ import subscript_arguments

This sort of change in behaviour is exactly why the future mechanism was 
invented. If it is desirable to change subscripting to pass multiple 
positional arguments, then we should use that, not complicated jerry- 
rigged "Do What I Mean" cunning plans that fail to Do What I Meant.

Notice that none of the above needs to refer to keyword arguments. We 
could leave keyword arguments out of your proposal, and the argument 
parsing issue remains.



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

Reply via email to