Monday, May 10, 2010

The Lisp Ethos of Total Dynamicity

All true Lisps have a very important feature: you can enter any expression any time. (Subject to some static rules of course. E.g. you can't use a GO outside of an enclosing TAGBODY.) Heck, you can redefine a class while you're in the debugger that's waiting for you to continue with a restart.

So, I was quite shocked to learn that Python, heralded as a dynamic language, doesn't allow you to redefine classes. Of course, redefining classes isn't something you do all the time, but in Lisp implementations, supporting stuff like this is simply a question of honor.

Thank god Slava is kicking everybody's asses left and right outside of Lisp proper. I hope this will lead other dynamic language implementors to adopt the same ethos.

In my own Lisp implementation adventures, I was (of course!) seduced to think that maybe such total dynamicity could be sacrificed. After all, I can just restart the app I wrote to have the changes take effect. But in the end, it just wouldn't be a true Lisp. And it would add a load of bollocks to the language and its specification.

3 comments:

shawn said...

Python allows you to redefine classes. Existing instances of that class however are not redefined, they still refer to the old class.

A programmer can choose to reload subclasses and any existing data structures on redefinition. In Lisp obviously all instances refer to the new definition.

I'm not sure from a pragmatic perspective why this makes Python any less dynamic.

Manuel J. Simoni said...

For me, dynamic means being able to change things at runtime. With this meaning, a language is more dynamic than another, if it allows you to change things that you can't change in the other (such as the methods and slots of instances of existing classes in this case).

Is redefining classes relevant from a pragmatic perspective? I'm not sure, but I think so, yes. At least, it can mean the difference between being able to keep working on a running program, versus having to restart it. All other things being equal, I'd take a language that has that feature.

shawn said...

It is trivial to implement a metaclass tracker that reloads existing instances upon redefinition and module upgrades via weak references.

Here is an old recipe: http://cl.ly/167f

I would hazard a guess that since it is a corner case that would affect the size of every class with side-effects on existing code and for which a solution is easily had by only those needing the feature are probably why it is not part of the python specification.

I believe CLOS impls mostly put off object redefinition until the next object access. You still have "old" objects after redefinition.

I also think a better way to describe this language feature is interactive rather than dynamic. Both python and lisp provide dynamic class redefinition. Lisp affords a more straightforward manner to interactively work with redefined objects with less code.

Erlang would provide a nice comparison here.