[Types-sig] RFC 0.1

Tim Peters tim_one@email.msn.com
Thu, 16 Dec 1999 20:17:05 -0500


[Guido]
> ...
> If it's (OPT) we're after, adding run-time checks can never obtain
> your goal.

That's unclear:  declared types don't have to be known correct to be useful!
They at least tell you what the user *expects* to be true.  Code can then be
generated *assuming* everything the user said is true, with a block of code
preceding to *verify* it's true.  Optimizing compilers do this routinely
under the covers, where the (misnamed in this case) "verification" code
simply branches to a slower all-purpose translation of the code if the
assumptions turn out to be false at runtime.

Trivial example:

    for i in range(n):
        x[i] = i

In the presence of

    decl x: [Int]

the generated (pseduo)code

    if type(x) is not ListType:
        raise TypeError("lying bastard!")
    else:
        setter = ListType.__setitem__
        for i in range(n):
            setter(x, i, i)

is a good bet and already saves n lookups of the proper __setitem__ method.
It's a comparatively small step from there for a compiler to say "ah, but I
know all about Lists!  I can generate list "setter" code inline".  And again
from there to "ah, now that all the code is exposed, I know the net effect
on each i's refcount, so can skip useless inc+dec pairs".

I'm not saying you need <wink> to do this; just saying that all information
*can* be valuable to a gung-ho optimizer -- even wrong information!
Optimization is a probability game, and while certainty is helpful it isn't
essential.

> ... if there's a type error in my except clause, what good does it
> do me to get a type-check error at run time?

Frankly, I think the "safety" arguments are the weakest -- if someone has
untested code paths in their program, they should *assume* all such paths
are broken!  What good does it do you to have a statically type-correct
except clause if it raises an OverflowError at runtime <0.5 wink>?
(Speaking of which, I routinely see error paths in C++ apps blow up with
memory errors due to null pointers.)

>>> The initialization for b denies its type declaration.  Do you really
>>> want to do this?

>> None is a valid value for any type as with NULL in C or SQL.

> No.  In C, NULL is not a valid integer (at least not conceptually --
> it's a pointer).  I hate the fact that in Java, NULL is always a valid
> string, because strings happen to be objects, and so I always run into
> run-time errors dereferencing NULL.  I'd like to be able to declare
> the possibility that a particular value is None separate from its type
> -- this feels much more natural and powerful to me.

Paul later semi-suggested borrowing Haskell's notation for union types.
This looks good to me (despite that "my" syntax looks concrete, it's
abstract <wink>):

    decl i: Int           # "i = None" not allowed
    decl j: Int | None    # "j = None" is OK

As you said earlier, "a type" is a set of values.  So if None is a legit
value for a name, then None is in the set of values that name can take on,
so None is certainly a part of its type.  We don't need tricks or
compromises here:  we can say what's intended directly.

> The hard part is keeping which variables (and arguments, etc.) can
> contain instances of a given class; if we have that we can track
> instance variable assignments.

I don't see the problems here, at least not for explicit declaration
schemes.  The inference schemes are harder -- because they're, well,
*harder* <wink>.

loathe-to-see-hard-problems-prevent-solving-easy-ones-ly y'rs  - tim