python improvements (Was: Re: New Language)

Martijn Faassen m.faassen at vet.uu.nl
Tue May 16 18:06:15 EDT 2000


Neel Krishnaswami <neelk at brick.cswv.com> wrote:
> Martijn Faassen <m.faassen at vet.uu.nl> wrote:
[snip]
>> What about classes and methods though? If you want to optimize some of
>> the dispatching it may be pretty helpful to have static typing.

> Strong typing doesn't help with dispatch elimination except in
> combination with something like Java's 'final' classes or Dylan's
> 'sealed' classes, or if you do whole-program analysis (like Cecil's
> Vortex compiler does).

> This is because in order to eliminate a dispatch, you need to know the
> direct class of an object, rather than just "this is an instance of
> some subclass of Foo". For example, you couldn't do dispatch
> elimination in this function:

>     def square(n: Number):
>     	return n * n

> because the hypothetical Number class isn't a leaf class of the class
> hierarchy. (Well, you could if you could do interprocedural dataflow
> analysis and were able to prove that a particular call to square()
> would receive a machine integer or float, but that's a *lot* of work.)

Sure, but you could optimize *some* of the dispatching if you did
know the particular class of an object. Of course whether that's a
good idea is another point. And wouldn't it be possible to at least
optimize the dispatch tables somewhat if you knew an object was a
subclass of something? It would be tricky, but you might be able to
cut through some hash table lookups. Don't know if that'd gain you
a lot, though. 

I'd agree with you in general that optimization of this could perhaps
better be solved by other ways than static typing. Method caching
indeed sounds interesting.

>> Similarly, in a dynamic system you'd *lose* your nice declarations
>> as soon as you pass them into some function that doesn't have them
>> (barring type inferencing, which is about as non-easy as static typing,
>> if not more :).

> Lisp compilers are pretty smart about this: if you pass a typed
> function to a dynamic fn, it will check the types on the function and
> raise an error if they don't match. When they *can* compute all the
> types then they don't do the checks. 

> I don't know if anyone has written an OO language that supports type
> inferencing -- I was under the impression that adding subtyping rules
> to Hindley-Milner type systems made them undecidable.

Hm, I don't know much about ocaml, but the language does some type
inferencing as far as I'm aware, and it supports objects. Perhaps
someone more knowledgable about it (you? :) could comment.

>> > Before static typing for speed is tried (with its complicating effects
>> > on implementation), I think it's better to go for the factor of 2
>> > improvement that can be won via easy tricks like method caches,
>> > variable lookup optimization, and reducing function call
>> > overhead. (Look at Squeak Smalltalk for an example.)
>> 
>> Definitely agreed. (method caching may not always be that easy, though,
>> given __getattr__ and friends..)

> True. I wouldn't mind if there were a smaller hammer than __getattr__,
> though -- usually I want to catch only a few attributes dynamically, 
> rather than all of them. 

A nice syntactic hammer for getter/setters might be useful.

I suppose a __getattr__ wouldn't be unsurmountable, though. You could
cache a reference to the method that's looked up if in fact it's 
implemented by an actual method. Have a cache that's a hash with as
keys the object references and the method names, and as values references to
the method objects. When there's a method lookup:

  * check that table first, if it's in there, call the method found

  * otherwise do normal lookup

  * if found outside __getattr__, cache it in table (insert some smart
    caching rule here)

  * do rest of handling

You could do something similar for attribute lookups.

The tricky parts are classes that play with their methods, objects that
change their classes, etc. Perhaps it's possible to catch these special
cases and have them invalidate the record cache as far as the objects
in question pertain. Alternatively we could have those objects or
classes somehow indicate they're 'special' and that they don't want to
partake in the caching mechanism.

Do I get the ideas right here? I don't have any practical experience
with this. I wonder how much of a speedup one might get compared to the
current scheme. If it isn't significant it's not worth it.

Also there's of course the question whether dealing will all kinds of
optimization bugs is worth it.

>> >> ERR -- we get more robust code as the types are checked. It's nice when
>> >>        this happens during compile-time, though run-time can also be
>> >>        helpful.
>> 
>> > With an interactive read-eval-print loop, run-time is just as good as
>> > compile-time, IMO, because you can test your system incrementally, as
>> > you build it.
>> 
>> Not all people agree on this. I think some interface conformance
>> checking at compile-time would for instance be nice. But I
>> definitely agree that the ERR component of static type checking is
>> overrated.

> That's why I put in the IMO. :)

You're right. :)

> Seriously, types are most helpful to
> me as documentation of intent, and as it happens I try to put the
> types of arguments into the docstrings of code I write.

I tend to do that as well. Still, it would be nice if there was a
structured interpreter-checked scheme for this.

> I have experimented with automatically checking the docstrings (see
> http://www.sff.net/people/neelk/open-source/TypeChecker.py), but it
> was never useful enough for me to pursue very far.

Oh, so you agree with my previous statement. I'd agree it isn't 
something I yearn for a lot either. Coming from C++ I'd have thought
I'd needed it more than I do. Types really do seem overrated, especially
given a decent namespace and error reporting system.

Regards,

Martijn
-- 
History of the 20th Century: WW1, WW2, WW3?
No, WWW -- Could we be going in the right direction?



More information about the Python-list mailing list