[Python-3000] More wishful thinking

Talin talin at acm.org
Sun Apr 16 23:43:29 CEST 2006


Guido van Rossum <guido <at> python.org> writes:

> On 4/15/06, Talin <talin <at> acm.org> wrote:
> > Another grab-bag of language ideas / wishes. Some of these are
> > items that have been raised before on other lists - I want to get them
> > written down so that they can be rejected quickly :)
> >
> > 1) I don't know if this is already on the table, but I sure would like
> > to be able to have more options as far as mixing positional and
> > keyword arguments.
> 
> I agree. Please produce a patch that implements what you want.

All right, in that case, I'd like to post a general implementation
strategy for criticism before I end up going too far down the
wrong path.

As I see it, the problem breaks down into 3 parts:

-- parsing
-- representing the argument list
-- executing a call

The parsing part  is fairly straightforward. The new syntax would
allow keyword arguments to appear anywhere in the argument
list, intermixed with positional arguments, and after the varargs
argument.

(It would be possible to have non-keyword arguments after the
varargs argument as well, but that's harder to implement, and I
don't really see the value in it.)

The kwargs argument would remain unchanged - there's no real
reason to allow it to be moved around in the argument list.

So the argument list syntax would be (in psuedo-grammar):

   (keyword | positional )* [*varargs] keyword* [**kwargs]

(This is of course omitting all of the complexities of generator
expressions for the moment.)

Representing the argument list. The current _arguments struct
looks like this:

  struct _arguments {
          asdl_seq *args;
          identifier vararg;
          identifier kwarg;
          asdl_seq *defaults;
  };

The approach that I would take would be to remove the 'vararg',
and instead put the vararg argument into args. A special sentinel
value in the *defaults array (say, (void*)-1) would be used to
indicate that this argument was a varargs argument.

Thus, for each argument (other than kwargs), you would have
both an argument name and a default, where a NULL value indicated
a positional argument, a non-NULL value indicated a keyword argument,
and a sentinel value indicated a varargs argument.

Executing a call: This is the tricky part. Specifically, we want to insure
that the mapping of values to formal parameters remains the same
for existing code.

Start with a list of unfilled slots, one per formal parameter, including
the varargs parameter.

for each argument:
   if it is a keyword argument:
      find a the named slot;
      if found:
         if it is already filled, raise TypeError
         otherwise fill the slot with the argument
      else if there's a kwargs,
         add it there
      else
         raise TypeError
   if it is a positional argument
     if the next slot is a varargs slot
         append to the vararg list
     else
         fill the slot with the argument
         increment the slot index

There might be a more optimal implementation of this, in particular
it should be possible to create the varargs tuple in a single allocation
rather than having to build it up incrementally.

Anyway, if this seems unreasonable, or if you find any bugs let me
know. I have a lot on my plate at the moment, so I don't know when
I will get around to making the patch, but hopefully soon.

-- Talin




More information about the Python-3000 mailing list