[Edu-sig] Reloading code (was Re: OLPC: first thoughts)
Paul D. Fernhout
pdfernhout at kurtz-fernhout.com
Sun Feb 25 03:03:58 CET 2007
kirby urner wrote:
> On 2/24/07, Paul D. Fernhout <pdfernhout at kurtz-fernhout.com> wrote:
>
>>There may be one major semantical issue, in terms of the meaning of side
>>effects when loading a module (e.g. defining singletons, opening files,
>>etc.) which is hard to deal with generically with Python. You can deal
>>with [it] specifically in how you write your own code, but that is not a
>>general solution.
>
>
> Not sure I follow yet. A module loads top to bottom, with lower defs
> premised on
> those previously mentioned. Is that what you mean? Once everything is loaded,
> it's more like a __dict__, i.e. the namespace of the module of
> accessible, either
> via dot notation, or directly if the names are top level.
To step back for a minute, the fundamental problem here is that for
whatever reason a programmer wants to modify just one method of an already
loaded Python class (which came from a textual module which was loaded
already), save the change somewhere so it can be reloaded later
(overwriting part of the textual module?), and also have the program start
using the new behavior for existing instances without any other side
effects arising from recompiling this one change. In practice, this is
trivial to do in almost any Smalltalk system; it is hard if not impossible
to do in any widely used Python IDE or program (even when a Python shell
is embedded).
Unfortunately, the paradigm used by every Python IDE I've tried is to
reload an entire textual module (or more typically, entire program) at a
time for even the slightest change to one function. Embedded Python shells
generally allow you to redefine a function if you have a copy of the code,
but they offer no way to save the code. Most Smalltalks uses a different
paradigm, where code is presented to the user one function at a time in a
browser and is compiled one function at a time. Yes, there are cases where
people "filein" Smalltalk code defining a complex program, but such
fileins are generally considered an *interchange* format, not a preferred
program representation for editing unlike as is usually the case with Python.
Consider the meaning of an arbitrary piece of Python code near the bottom
of a textual module. Essentially, you have no idea what it means if the
original author has used some Python bells and whistles. For example, he
or she could have defined a metaclass where every nested "def" under a
class was converted to, say, an uppercase string and stored under a key
that was the numerical hash of the function name (with no functions
actually defined for that class perhaps). The specific metaclass behavior
may even hinge on the current state of a global which has been modified
several times during the course of loading the module. So essentially, you
have no way of knowing for sure what any apparent Python code really means
by isolated inspection. And because any module can run any arbitrary
Python code, without actually running the Python program (or doing the
equivalent analysis), you can never be sure what side effects loading a
module has. Now, Smalltalk has metaclasses too, but in practice, because
of the way code is presented to the user and edited and recompiled one
method/function at a time, the context makes fairly clear what is going to
happen when that snippet of code you just changed is compiled. The big
difference is really the effective unit of compilation -- the complex
module in Python or the simple method/function in Smalltalk.
Now, this is rarely a problem the *first* time a module is loaded, but it
generally becomes a problem when a module is *reloaded*. If you only
treated as module as an *interchange* format, and then modified the live
classes using a tool which only works on regular classes (like PataPata
does), there is no need to reload the module, so this potential problem
related to parsing a modules meaning via an IDE tool remains only
potential, and also avoided is the possibility reloading a module might
have side effects. (In practice, anything still depends on mapping from a
function back to its source text, and this may go wrong for various
reasons... :-)
Naturally, this kind of major redefinition is rarely done, and it would
create lots of confusion, but it is possible, so IDE tools that do not
support it are incomplete. This is a perrenial problem with, say, C, where
you can make all sorts of macros and so never know just exactly what
arbitrary C code out of context does (see the obfuscated code
contests...). And it means that you can't get a simple one-to-one mapping
of a section of a file that looks like it defines a function and an actual
function reliably without analyzing the entire program. Yes, 99.99% of the
time Python code does the obvious thing, but it is not 100% certain. The
same is true for Forth -- in theory any isolated snippet of Forth can mean
anything, since it is trivially easy to modify how the compiler interprets
text -- something that make Forth very powerful but at the same time
potentially very confusing for a code maintainer. I don't have the link
offhand, but a while back I came across a blog post suggesting you tend to
either have a powerful language or powerful tools -- but not at the same
time (except perhaps for Smalltalk :-). That is because if the language is
very flexible, it becomes almost impossible to write IDE tools that can
keep up with it in all its generality.
Now, since almost all Python code is written in a straightforward manner,
one can still make such tools and find them useful. But likely there will
aways be gotchas in such systems as long as they tie their operation
closely to the notion of compiling one module at a time, compared to
Smalltalk which ties itself to compiling one method/function at a time.
One of the things PataPata tried to do, and succeeded to some extent, was
breaking the link between reloading a textual module and modifying a
running Python program, yet it was still able to use a textual Python
module as both an interchange format and also an image format (something
even no Smalltalk has done to my knowledge, as all Smalltalk images I know
of are binary, not human editable text).
One idea I have wanted to try for Python but never got around to it is to
create a Smalltalk-like browser and build and modify classes on the fly by
changing their objects and compiling only individual functions as they are
changed; I could store the textual representation of functions in a
repository with version control. Then, I could also still use Python
modules as an interchange format, sort of like PataPata did but without
prototypes. You would lose some of the generality of coding in Python
(setting globals in a module and such) but you would essentially have a
somewhat Smalltalk like environment to mess with (ignoring restarting from
exceptions, which is very important in Smalltalk development, where much
code ends up being written in the debugger as often as not; I'm not sure
whether that part could be simulated with plain Python or whether it would
require a VM change).
--Paul Fernhout
More information about the Edu-sig
mailing list