Re: passing/catching a variable number of args in python

Daniel LaLiberte (liberte@ncsa.uiuc.edu)
Wed, 11 Dec 91 11:34:00 CST

>Implementing this change to the "language" would only involve taking
>out code to handle the special cases.

Which special cases?

I guess I was only thinking of one special case: in argument passing, if
there is one formal argument in a function declaration, then no matter how
many actual arguments are given, they are all packaged up in a tuple for
the one formal argument. So for

def f(x) ...

The call f(1, 2) puts the tuple (1, 2) in x.
This case has some similarity with the following, but they are quite
different nevertheless.

def f(x, y) ...

f((1, 2), 3) -- x is given (1, 2).

----
Consider the following.

def f((x, y), z)

f((1, 2), 3, 4) -- an error
f((1, 2), (3, 4)) -- so parens around 3, 4 is required
f((1, (2.1, 2.2)), (3, 4)) -- y gets (2.1, 2.2) I have no problem here

def f((x), y)

f((1), 2) -- x gets 1
f((1, 2), 3) -- this I don't like. should x get tuple (1, 2)? I say no.
-- an error would be more consistent. what does python do?

What exactly is the new convention you are proposing? That "a,b=1,2,3"
assign 1 to a and (2,3) to b? I would be vehemently opposed to this,
as well as to its equivalent in argument passing.

I would be opposed too. In fact, I am going the other direction.

a = 1, 2, 3 has the same problem described above
as def f(a) given f(1, 2, 3).

I propose that instead of a = 1, 2, 3, one must say a = (1, 2, 3)
and instead of def f(a) given f(1, 2, 3) one must say f((1, 2, 3)).
Or if one wishes to break out the components of a tuple in a function,
one could def f((x, y, z)) and be given the same f((1, 2, 3)) or just
f(xyz) where xyz = (1, 2, 3). But def f(x, y, z) can only be given
three separate arguments, e.g. f(1, 2, 3).

The rule is that for a left hand side (or formal argument list),
there must be a one-to-one correspondence between names and values on
the right hand side (or actual argument list). This same rule is applied
consistently recursively.

To implement this, you could still build an implicit tuple out of
actual arguments, but build the corresponding implicit tuple out of formal
arguments and do the matching on corresponding elements of the tuples,
recursively. The same for assignment.

Now that I have presented it more clearly, I am more convinced myself that
this is the right way to go. I am not sure how this proposal fits in with
zero argument functions and methods and (1,) style tuples, but I would
bet that doing away with this special case makes other things simpler.

Had you considered matching corresponding elements of lists too?
So def f([a, b]) could be given f([1, 2]).

Some way of doing explicit optional and rest arguments could be added
given this new consistent convention. So def f(a, b?, c*) might mean b is
optional and c gets all following arguments in a tuple. f(1, 2, 3, 4)
puts (3, 4) in c. But f(1, 2, 3) puts (3,) in c. f(1) puts Novalue in b
and perhaps () in c.

dan