On 5/21/06, Collin Winter <[EMAIL PROTECTED]> wrote: > On 5/21/06, Aahz <[EMAIL PROTECTED]> wrote: > > On Sun, May 21, 2006, Collin Winter wrote: > > > > > > This is something I've been meaning to bring up: if we're serious > > > about the "tuples = fixed-length collections, lists = unknown-length > > > collections" distinction, then the CPython core should switch over to > > > this mindset as well. The fact that Python 2.x uses a tuple for > > > *varargs has caused me to jump through a number of hoops in my own > > > typecheck package. > > > > This is a guideline, not a rule, and the speed and size of tuples make > > them more appropriate for varargs. > > Honest question: what is so special about *varargs that demands > tuple's speed and size characteristics?
I'm not sure -- it might depend on the application. But I can shed some light on this like no-one else... :-) It's mostly a historical accident. A very early version of Python didn't have *varargs, but had a different feature: f(a, b, c) was equivalent to f((a, b, c)). Also, def f(a, b, c) was equivalent to today's def f((a, b, c)). This was all borrowed from ABC (which went one step further -- f a was equivalent to f(a); but I didn't like that enough to copy it). The idea was that a function really had only one argument, and that multiple arguments were simulated by passing a tuple -- just like what we still do for return values. A varargs function was then declared with a single argument and called with multiple ones. For example, this was a common idiom for a varargs method: def foo(args): self, args = args[0], args[1:] ... It was a bit trickier to write code that would also handle the case where there were zero args -- because then the single argument wasn't turned into a tuple! The realization that this was a common use case made me change it all around, to the current model. (I think keyword arguments and default values came a bit later.) The conclusion to draw from this history lesson is that the interpretation of an argument list as a tuple was logical in the original version, since syntactically it *was* a tuple (except in f(a), where it *wasn't* -- just like (a, b) is a tuple but (a) isn't). Tuples ended up significantly in the implementation as a result of the early version, and the rewrite didn't remove them, since all C code was also expecting tuples and I didn't want to have to change that -- except there was also C code that expected that a *single* argument was *not* passed as a tuple, and for the longest times there were hacks to work around that expectation: track the history of PyArg_Parse and friends. Nowadays the implementation contains a variety of hacks to *avoid* creating tuples during a call -- since the arguments are present on the caller's stack in the right order, it's often easier to present the callee (at the C level) with a count and a pointer to an array of objects. But since *args historically returned a tuple, if it is present, a tuple is created. Since **kwds is already a dict (i.e. a mutable container) and since we long accept a list for *vargs on the call side, I think it is actually more logical to use a list for receiving *args. -- --Guido van Rossum (home page: http://www.python.org/~guido/) _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com