On Sat, Sep 26, 2020 at 07:12:00PM -0400, Ricky Teachey wrote:
> Another inconsistency is that the case of keyword arguments only would bind
> the RHS value to the first positional argument, which is the index, and not
> the value. I think this is what Guido was referring to when he responded
> talking about introspection being required? Not sure.
> 
> in any case, to me that doesn't seem like such a big deal period it might
> lead to some weird error messages but I'm not sure why it's such a big
> problem. Maybe it poses a difficulty for type hinting?

I had a few paragraphs about exactly that scenario in my earlier post, 
but I deleted it because I didn't think it would be popular. So let me 
see if I can recreate it from memory.

You are suggesting that if there is no positional index, the interpreter 
should just pack the value into the left-most parameter. Here's the 
signature of my method:

    # Round 1
    def __setitem__(self, index, value, *, spam=0):

and the caller uses this:

    obj[spam=1] = 99

so 99 gets packed into the index and the exception says something like:

    TypeError: missing 1 required positional argument: 'value'

which is surely going to confuse a lot of people, because the value is 
clearly 99. It's the index which is missing.

Round 2: change the signature.

    def __setitem__(self, index, value=None, *, spam=0):

and now the parameters get packed as index=99 and value=None, so there's 
no exception, but that looks like `obj[99, spam=1] = None` which would 
be indistinguishable from a perfectly normal call.

Round 3:

    SENTINEL = object()  # Private sentinel value for subscripts.
    # Or maybe use NotImplemented?

    def __setitem__(self, index, value=SENTINEL, *, spam=0):
        if value is SENTINEL:
            value = index
            index = SENTINEL  # or raise
        if index is SENTINEL:
            # Handle keywords with no index
        else:
            # Handle index + keywords

and now we have something usable.

That's not a lot of boilerplate code, but if you don't write it, you 
get a weirdly misleading error message, as in Round 1 above.

Ultimately I think it's going to be up to the PEP authors to decide what 
they want to propose here. I think we now have these choices:

1. Fill in a default index with one of:

a. None
b. empty tuple ()
c. NotImplemented
d. a new, unhashable builtin Missing or NoIndex

2. Prohibit keyword-only subscripts.

3. Bind the right-hand side value to the index parameter, and leave the 
value parameter blank (as above).

Did I miss any?

There are probably more heavyweight alternatives that require changes to 
parameter binding, or new dunders, or runtime introspection of the 
dunder, but I'm not sure that the PEP authors want to consider those 
(and if they do, they should probably be in a competing PEP).

I think that: 

1a. is difficult (but not impossible) for numpy to use;

1b. makes a certain sense but is confusable with an actual tuple subscript;

1c. recycles an existing builtin that is very unlikely to be currently 
    used as a subscript;

1d. avoids any chance of that, but requires a new builtin;

2. would be disappointing but I could live with it;

3. feels ugly and inelegant and will probably confuse people.


Stefano, Jonathan, I think that if there's no more comments on this 
specific issue in the next few days, it's up to you now to make a 
choice, put it in the PEP, list the alternatives as above and why you 
are rejecting them (perhaps by linking to this thread -- you don't have 
to recap the entire discussion inside the PEP, just a brief summary).



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

Reply via email to