Re: Optional Static Typing -- Stop the Flames!
Posted: Jan 7, 2005 5:59 PM
Things That Are Good
I can handle
adapt as a function name.
I also like the separate interface syntax well enough to not complain.
I would caution against using a colon for type specifiers. The colon is threatening to become Python's curly brace. If there are 18 colons on a line, it will become difficult to read.
What do types on
**kwargs mean? Will the internally used tuple and dict be adapted to that type? That's the only thing I can think of that even comes close to being intuitive...
Is it good to evaluate the type expressions at define-time? Could using namespacing to evaluate these save us the later trouble of doing parameterized types?
I like the interface idea. However, could type specifiers only accept interfaces or types, not classes?
The reasoning goes like this, you can't duck-type integers or strings. They are what they are. This is what types do, it specifies which data is core data--it's primitive. Classes are constructed to implement interfaces of one type or another. This is why could completely hose duck-typing.
If we type based on core-data, then only a certain type or subtype is acceptable, since you can't "imitate" an integer or a string--only subtype them to adjust behavior or add methods. However, when we specify classes, the case is not so clear-cut. I will now describe my worst nightmare.
Take the situation where I have to use a framework that does this:
def file_mangler(x: myFileHandleClass):
Now assume myFileHandleClass does something unacceptable in one of the base __init__'s, (or worse, in __new__). For example, let's say I'm going to put network support into this framework. Before I could implement my own class and duck-type it to behave like the myFileHandleClass.
With non-Pythonic type specifiers, I have the problem of having to either implement a subclass of a broken class or the other coder must have the foresight to use an interface, not a class, in the type specifier. Now, I will get an exception, because my duck-typed class cannot be adapted to myFileHandleClass. There is no good way that an adapt function can predict the duck-typing. This MUST be for Python to remain "My Python". Again, it should not be possible to specify that only a certain CLASS may be passed in.
My gut reaction, then, is to only allow types or interfaces to be specified. In most other Statically Typable languages, classes can be specified here. As far as I am concerned, this is what hamstrings their ability to duck-type. A class is not a type, it shouldn't be treated as one. A class has behavior, that's what's important, and that's what an interface indicates.
Also, it is important to support specifying interfaces post-hoc.
Without either of the above, other programmers mistakes limit my ability to duck-type and clever-glue-class my way out of those mistakes.
Actually, Should interfaces actually be special types? I understand that they wouldn't be useful for actually instantiating data, but perhaps that's what we're looking for. It would be especially useful for bridging the gap created with lists and dicts. Right now, we don't insist that things passed around actually be subclassed from
dict. We simply duck-type list and dict methods.
This actually has an elegance to it. Our
adapt implementation, assuming it attempts to duck-type interfaces, will need to match interface signatures to object signatures. Special cases will be needed for internal interfaces. Additionally, there are some interfaces that are more nebulous than just being an internal type primitive (generators/iterators). If we stash the signature information in the built-in types and have the interface syntax generate abstract types as interfaces, then the adapt information (and adaptation registry) could be encapsulated entirely in the existing type structures.
Look at the utility of the following example:
from types import types.IteratorType
# Note, this type is not actually instatiated, it just exists to integrate interfaces into the base language
class randomNumberGenerator implements RestartableIterator:
def encrypt(r: types.IteratorType):
This example means what it says and says what it means. No wierd inheritance acrobatics involved to trick it into accepting our class.
Again, I cannot stress enough, enforcing a certain CLASS is folly. Enforcing a certain TYPE is not (with some informational types provided, such as IteratorType, NumberType). Making interfaces generate types, retrofitting built-in types, making a few informational types, and allowing post-hoc interface specification will make this a feature with real utility.
You probably have a different feeling for types than I do. It might be there is an impedence mismatch between what you envision a type is and what I do.