On Wed, Jan 15, 2014 at 9:55 PM, Larry Hastings <larry@hastings.org> wrote:
On 01/15/2014 09:37 PM, Guido van Rossum wrote:
Well, I think these are mostly artifacts from old times, and usually passing None *should* be the same as omitting the argument. But check each case!
Vajrasky Kok's recent posting to python-dev discusses the same problem. His example is itertools.repeat's second parameter, which is slightly nastier. Consider the implementation:
static PyObject * repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { repeatobject *ro; PyObject *element; Py_ssize_t cnt = -1; static char *kwargs[] = {"object", "times", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|n:repeat", kwargs, &element, &cnt)) return NULL;
if (PyTuple_Size(args) == 2 && cnt < 0) cnt = 0;
I draw your attention to the last two lines. And remember, Argument Clinic doesn't provide the "args" and "kwargs" parameters to the "impl" function. That means two things:
itertools.repeat deliberately makes it impossible to provide an argument for "times" that behaves the same as not providing the "times" argument, and there is currently no way to implement this behavior using Argument Clinic. (I'd have to add a hack where impl functions also get args and kwargs.)
Passing in "None" here is inconvenient as it's an integer argument. -1 actually seems like a pretty sane default to mean "repeat forever", but the author has gone to some effort to prevent this. I therefore assume they had a very good reason. So again we seem stuck.
Are you suggesting that, when converting builtins to Argument Clinic with unrepresentable default values, we're permitted to tweak the defaults to something representable?
In this specific case it's clear to me that the special-casing of negative count is intentional -- presumably it emulates sequence repetition, where e.g. 'a'*-1 == ''. But not accepting None is laziness -- accepting either a number or None requires much more effort, if you need to have the number as a C integer. I'm not sure how AC could make this any easier, unless you want to special-case maxint or -maxint-1. In the sha1 example, however, accepting None and converting it to NULL (without a reference leak, please :-) seems fine though. -- --Guido van Rossum (python.org/~guido)