On Mon, May 25, 2020 at 02:19:57PM -0700, Christopher Barker wrote:

> > It's an extremely common idiom right up until it doesn't
> > work, and you need:
> >
> > _SENTINEL = object()
> > def fun(..., option=_SENTINEL):
> >     if option is _SENTINEL:
> >         option = something_else
> >
> 
> I've thought to a while that there should be a more "standard" way to so
> this:
> 
> A NOT_SPECIFIED singleton in builtins would be pretty clear.
> 
> (though I'd like to find a shorter spelling for that)

Guido's time machine strikes again! We already have that "not specified" 
singleton in the builtins, with a nice repr. It's spelled "None".

The problem is that this is an infinite regression. No matter how many 
levels of "Not Specified" singletons you have, there's always going to 
be some context where they are all legitimate values so you need one 
more. Think about a function like `dir()` or `vars()`, which can operate 
on any object, or none at all:

`dir()` is not the same as `dir(None)`, so we need a second sentinel 
MISSING to indicate the no argument case;

but now we would like to say `dir(MISSING)`, so MISSING is likewise a 
legitimate value, and we need a third sentinel:

    since None is a legit value, we need MISSING;
    but MISSING is also a legit value, so we need UNDEFINED;
    but UNDEFINED is legit, so we need ...

and so on through NOT_SPECIFIED, ABSENT, OMITTED and eventually we run 
out of synonyms.

In the specific cases of `dir` and `vars`, it is easy enough to work 
around this with `*args`, but there can be functions with more complex 
signatures where you cannot do so conveniently.

Fortunately, if you have a function that needs such a second level 
sentinel, you probably don't care that *other* functions like `dir` 
don't treat it as a special sentinel. It's only special to your library 
or application, not special everywhere, so the regression stops after 
one level. But that wouldn't be the case if it were a builtin.

For the basic cases, using None is sufficient; if it's not, rolling your 
own is actually better than having a standard builtin, because:

- it is specific to your library, you don't have to care about how 
  other libraries might treat it (to them, it's just an arbitrary 
  object, not a special sentinel);

- you can choose whether or not to make it a public part of your 
  library, and if so, what behaviour to give it;

- and most importantly, you don't have to bike-shed the name and repr 
  with the entire Python-Ideas mailing list *wink*



-- 
Steven
_______________________________________________
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/4TLBG5XJNRABFKXHJR4A2ARRSUVASXNF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to