"I have a mind like a steel... uh... thingy." Patrick Logan's weblog.

Search This Blog

Tuesday, December 28, 2004

The ROI of Optional Type Annotations

From comments below...

How is the argument from reliability of Lisp and Erlang systems an argument against optional static type declarations?
The real question is, should optional type annotations be added to Python? I'd say no, the return on investment is not nearly as great as investing in several other implementation features.
In the Lisp world, you program with dynamic typing initially until the program stabilizes and the hot spots are known. You then type annotate just the hot spots to improve code generation of those hot spots (Lisp code is generally compiled), with the option to go to C to improve the hottest of the hot spots.
Optional type annotations were added to Common Lisp in the early 1980's. Compiler strategies have improved a lot since then, as have machine capabilities. I think a better return would come from investing in the implementation of the current Python language rather than changing the Python language itself.
Basically, type annotations in Lisp (and, one presumes, Python) are an upside option that you can but don't have to use. Writing Python code (or Lisp code) from scratch with type annotations would be pretty silly. (Or, to put this another way, in Lisp type annotation is a performance, not a reliability feature).
I think the downside of having every Python programmer have to understand the best practices of optional type annotations would be far worse than the upside of having them. To repeat myself, the investment should be made "under the hood" of the current Python language.

3 comments:

PJE said...

There *are* other uses for type declarations besides type checking. For example, the Naked Objects framework in Java uses method signatures to figure out what actions might apply when one object is dragged-and-dropped onto another object in a GUI.

Documentation, of course, is an even more immediately useful use case. A good syntax would be more precise and more brief than docstring explanations. And, such information can be cross-referenced -- if you're looking at a method that takes an IFoo, it's nice to be able to jump to the documentation for IFoo.

Last, but far from least, declarations are useful in interfacing to code built in languages that have declarations. Interfacing to C, Objective-C, C++, C#, and Java would all be much easier if type declarations were available -- even if the Python language itself had no semantics for such declarations!

In other words, what I'm saying is that declarations could be a purely syntactic/metadata feature, and they'd still be quite useful for many things.

Note, by the way, that people have interfaced to those other languages with Python already, but the APIs can be quite awkward because there's no simple way to argument/return/attribute metadata. So, having such annotations would be an immediate win for those interface tools. An important part of Python's heritage and future is that it is "universal glue" -- it doesn't shy away from talking with other languages, whether those languages are static or dynamic.

Is there a danger of over-declaration by newbies? Sure. I'd probably find it really annoying to use code with excessive declarations, if those declarations actually restricted anything. However, if they were *just annotations* (or were adaptation specifiers per PEP 246), then I could still pass their code any darn thing I pleased, and we could all continue to be happy.

Anonymous said...

In none of the dialogue on this topic have I heard boost::python mentioned.
Why not let just migrate the application pieces that would benefit from C++ification migrate gacefully into boost::python, and resist the temptation to 'sex up' what is truly a beautiful product?

PJE said...

"""Also, I don't like them so much, but look at PEAK's generic functions for another take on this,"""

I've looked; in fact I wrote them. :)

Seriously, for simple type-based dispatch, an inline way of specifying type or interface would be quite nice for generic functions.

My point is that I'd like to be able to introspect on argument type -- from *outside* the function. For example, if arguments had type data available via 'inspect.getargspec()', then I could do something like:

@somegeneric.when()
def something(x:int, y:str):

instead of the current:

@somegeneric.when("x in int and y in str")
def something(x,y):

As I said, I don't care if the syntax is pure documentation, as long as it's introspectable.

Another interesting use is that one could have a metaclass that inspected the constructor's argument types to define a relational schema for that class... Anyway, there are zillions of applications (imo) for being able to annotate arguments as well as functions. I personally don't want to see 'def foo(x@int,y@str)', though!

I might go for a style like 'def foo(x [int], y [str])' though, as that would help emphasize the optional and descriptive (as opposed to restrictive!) nature.

Blog Archive

About Me

Portland, Oregon, United States
I'm usually writing from my favorite location on the planet, the pacific northwest of the u.s. I write for myself only and unless otherwise specified my posts here should not be taken as representing an official position of my employer. Contact me at my gee mail account, username patrickdlogan.