[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.