signature analysis ( was: getargs enhancement )

Steven D. Majewski (sdm7g@elvis.med.virginia.edu)
Tue, 8 Mar 1994 13:33:39 -0500

On Mar 8, 18:14, Guido.van.Rossum@cwi.nl wrote:
>
> Next challenge: come up with a syntax that lets me specify that an
> argument must be e.g. a list of (int, string) tuples or a dictionary
> whose keys are strings and whose values are lists of (int, string)
> tuples. Or am I asking too much?
>

Talking about "asking too much" reminds me... ;-)

Many long threads ago, when discussing type checking of arguments,
someone ( Guido? ) mentioned the possibility ( or was it just the
desirability) of adding some type of signature analysis to python.

I'm not asking for the implementation YET, but perhaps it's not
too soon to consider reserving the syntax for such a notion ahead
of time.

The Lisp/Scheme-ers, who also want optional type-checking, some of
which may be able to done at compile time, and some of which will
be done at run type, have also discussed this, and a good (IMHO)
suggestion that was floating around was to allow arglists where
each formal arg is either a single name, or a list of arg + test[s]
( I don't remember if it was a single test ( which would have explicit
AND/OR's joining clauses, or if it was a list of tests that were
implicitly AND-ed. )

A possible Python syntax would be to follow the lambda keyword and use
":" as in:

def f( str:type(str)==type(''), seq:hasattr(seq,'__getitem__') ):
def g( n:type(n) in ( type(0), type(0.0), type(0L) ) or hasattr(n,'__div__') ):
def h( n: 0 <= n <= 9, seq:len(seq)<=9 ):

Basically, what follows the ":" is a boolean expression which should
evaluate to true with the correct type argument. The semantics of the
expression would be the same as Lambda ( whatever that finally ends up
being! ;-) ... *Problem*: how can we fit Guido's lambda binding fix
syntax into the above? None of the above examples run into that
problem, but I would expect that someone who got tired of typing
"( type(0), type(0.0), type(0L )" would want to try:
"NumericType = ( type(0), type(0.0), type(0L) )"
or perhaps:
"isNumeric = lambda n: type(n) in ( type(0), type(0.0), type(0L))" )

I would propose that initially ( and minimally), the syntax be made
legal, even if it is currently unimplemented. There would also need
to be some kind of switch/function/variable/attribute to turn dynamic
checking on and off. ( My comments about global/local debug vars are
relevant here: how fine grained should the control be? per module?
class? function/method? ). An initial implementation of dynamic
checking would be to turn the tests into lambda's that get exec-ed
on or before function entry, TypeError, AttributeError, and false
evaluation of the test will all be folded into a single exception.

Various levels of static typechecking programs would be possible,
with, I suppose, the ultimate version, doing full type inference and
removing unnecessary or redundant dynamic tests.

The benefits:
Less work than manually inserting tests.
Easier to turn testing on and off.
If testing is OFF, it can be skipped on the Python compile, rather
than being nested in a runtime ( if DEBUG : ... )
The syntax documents the interface, even when checking is turned off.

The main argument AGAINST it is the argument that ran thru the whole
thread on type-checking : that maybe this type of type checking is
inappropriate and unnecessary for a language like Python. If this
*is* the overwhelming response, I'm willing to forget the whole thing!

- Steve Majewski (804-982-0831) <sdm7g@Virginia.EDU>
- UVA Department of Molecular Physiology and Biological Physics