[Python-Dev] type categories

Andrew Koenig ark@research.att.com
Mon, 26 Aug 2002 15:46:46 -0400 (EDT)


Guido> ABC did this, and very early Python did this, too (but Python always
Guido> required parentheses for calls).  However, adding optional arguments
Guido> caused trouble: after

Guido>   def f(a, b=1):
Guido>       print a*b

Guido>   t = (1, 2)

Guido> what should

Guido>   f(t)

Guido> mean?  It could mean either f((1, 2), 1) or f(1, 2).  So we had to get
Guido> rid of that.  I suppose ML doesn't have optional arguments (in the
Guido> sense of Python), so the problem doesn't occur there; that's why it
Guido> wasn't a problem in ABC.

Right -- ML doesn't have optional arguments.
It does, however, have clausal definitions, which can serve a
similar purpose:

	fun f[a, b] = a*b
	  | f[a] = a

Here, the square brackets denote lists, much as they do in Python.
So you can call this function with a list that has one or two elements.
The list's arguments must be integers, because if you don't say what
type the operands of * are, it assumes int.  If you were to call this
function with a list with other than one or two elements, it would
raise an exception.

You can't do the analogous thing with tuples in ML:

       fun f(a, b) = a*b
         | f(a) = a

for a rather surprising reason:  The ML type inference mechanism sees
from the first clause (f(a, b) = a*b) that the argument to f must
be a 2-element tuple, which means that in the *second* clause,
`a' must also be a 2-element tuple.  Otherwise the argument of f
would not have a single, well-defined type.

But if `a' is a 2-element tuple, that means that the type of the
result of f is also a 2-element tuple.  That type is inconsistent with
the type of a*b, which is int.

So the compiler will complain about this definition because the
function f cannot return both an int and a tuple at the same time.

If we were to define it this way:

       fun f(a, b) = a*b
         | f(a) = 42

the compiler would now accept it.  However, it would give a warning
that the second clause is irrelevant, because there is no argument you
can possibly give to f that would cause the second clause to match
without first causing the first clause to match.