Adding static typing to Python

Quinn Dunkan quinn at regurgitate.ugcs.caltech.edu
Fri Feb 22 17:25:59 EST 2002


On Fri, 22 Feb 2002 16:14:03 +0000 (UTC), gbreed at cix.compulink.co.uk
<gbreed at cix.compulink.co.uk> wrote:
>Quinn Dunkan wrote:
>
>> >But you can do that in Python:
>> >
>> >>>> def area(shape):
>> >...   if isinstance(shape, Circle):
>> >...     return math.pi*shape.radius**2
>> >...   if isinstance(shape, Rectangle):
>> >...     return shape.width*shape.height
>> >...   if isinstance(shape, Square):
>> >...     return shape.width**2
>> >...   raise TypeError, "unknown shape"
>> >...
>> 
>> This kind of giant typecase is exactly the sort of thing that OO is 
>> supposed
>> replace.
>
>Yes, but then are overloaded functions "OO" either?

Of course, that's what type-based dispatching, aka data driven whatever, is.
Consider the typical scheme OO reinvention, where you have a procedure that
accepts messages and returns functions, so you
(define (message obj) ((obj 'message) args)).  The point of all the trickiness
is that you can now call MESSAGE on any object that responds to 'message.
Effectively, MESSAGE is overloaded to have different definitions depending
on what (obj 'message) returns.

>> >You could make them all subclasses of Shape.  In which case, you have 
>> >functions defined to use a polymorphic object that depend on function 
>> >overloading by the real type.  Not all statically typed languages will 
>> >allow that.
>> 
>> C++ requires special keywords for it, but all statically typed OO 
>> languages I
>> know of do dynamic dispatch.  I certainly don't know every static 
>> language out
>> there, but just because there's a limited implementation somewhere 
>> doesn't
>> mean the concept is unworkable :)
>
>In Java, you need the same kind of "giant typecase" as in the Python 
>example you objected to.

Can't you just say 'shape.area()' and expect the right version of 'method' to
be called?  The typecase occurs automatically in the runtime vtable-or-whatever
lookup.

>                          I think C++ works the same way, unless you use 
>templates.  If I understand "dynamic dispatch" correctly, that's dynamic 
>typing by the back door, so not much of an argument for static typing.

No, dynamic dispatch doesn't have much to do with dynamic typing.  At least
that's my understanding.  Many implementations of static types (where "type"
is only a compile-time concept) make dynamic dispatch difficult, though, since
to do it you have to keep some type info around (hence c++'s vtables).
"Dynamic dispatch" is when you type "f(Shape *o) { o->area() }" and expect
that the actual 'area' function which called will depend on what type 'o'
happens to be at run time.

C++'s notion of an overloaded function leaves out the "at run time" part, so
in my view, it's just syntactic sugar for a different function name (usually
with lots of underscores and the types encoded somehow).

>> Sure you are.  area will reject objects that don't have the proper 
>> methods
>> defined for them.  How it works in haskell is that each class has a 
>> minimum
>> interface that you must implement.  If you don't implement all the 
>> methods
>> of the Shape class, Shape-accepting functions won't accept your objects.
>> This is less flexible than having to implement *only* the methods the
>> function actually uses, as in python, but c++ templates are sorta like 
>> that.
>
>If the types have to be resolved at runtime, you aren't getting static 
>type checking.

Sure.  In the description above, though, they're resolved at compile time
(what I meant by "Shape-accepting functions won't accept your objects" is
"your pogram won't compile").

>                What you describe is called "genericity" right?  I wasn't 

No.  What I describe (maybe not clearly) is called "type checking" :)

>thinking of that, and I did specify "explicit" above to exclude it.  AIUI, 
>Haskell does static, implicit typing and so long as everything's 
>statically compiled that gets you the same convenience as dynamic typing.

Not at all.  Haskell (and the MLs and various other hindley-milner relatives)
infers signatures automatically, but it's still statically typed.  It merely
saves you the trouble of typing up all those signatures (and many people
consider it good practice to type them explicitly anyway).  You're not going to
get a type error at run time (unless you consider a failed pattern match in
function application a type error).

>The proposed language changes for "optional static typing" all specify 
>types explicitly.  A more productive approach may well be "how do we alter 
>the language so that type inference can work?"  That may be why slots got 
>added.

No argument on that one :)  It's a little less intrusive.

>> >Wouldn't it be better to make area a method of the shapes?  And for 
>> static >typing, make it abstract in the Shape class?
>> 
>> In your above example, that's what it is.  You're just spelling 
>> 'circle.area()'
>> as 'area(circle)'.
>
>No, circle.area() and area(circle) mean very different things in Python, 
>so none of your comments on circle.area() really apply to area(circle).

What they mean depends on the definition of area().  len(circle) and
circle.__len__() mean the same thing in python, right?  (post 2.2 at least)

I also thought we were discussing a hypothetical non-python (hence the
"but this is not python" above).  

>That's a matter of taste, but you can get area() to work much the same way 
>Python implements len(), as
>
>def area(shape):
>  return shape.__area__()

That only works if area() has one argument.

>which still uses polymorphism rather than operator overloading.  (Time for 
>a definition of "polymorphism"?)

I'd call them the same.  "operator overloading" is when one function has
different implementations for different types, and "polymorphism" is when
you have a generic function that can work sensibly with different types.

>> I'm not even sure why the smalltalk style 'object followed by method' 
>> notation
>> caught on, especially since 'function followed by args' has always been
>> firmly entrenched.
>
>It happens to match the usual English word order: "the class's method" 
>rather than "the method of the class".  If the field had been dominated by 
>French speakers, perhaps it would have been the other way round.

Yeah, I've heard postfix function application described as "subject-verb" and
prefix application as "verb-subject", which indicates that people are thinking
linguisticly.  But I still think English has at least a strong orientation
around "the area of the circle" or "rotate the circle" or "the sorted list" all
of which are verb-subject.  Another hypothesis is that OO-heads wanted to
emphasize that their programs are conceptually data oriented, rather than
function oriented.  Could be the same reason they invented all that funny
"message" and "responds to" terminology.

I'm sure this has been discussed to death so I'll shut up now.  And it's the
sort of endless semantic debate that never gets anywhere :)



More information about the Python-list mailing list