Re: Jim Fulton : Extensible compound statements -- new exec flavor

Jim Roskind (jar@infoseek.com)
Wed, 1 Feb 1995 13:54:13 -0800

... well folks (other than Guido, who made a similar proposal) didn't
seem to like the my method of using try-finally (with boolean
variables) to accomplish control of locking/unlocking and
rollback/commit. :-(

Since I usually work to see if current syntax/semantics can cleanly
handle problems (before looking too hard at extensions), I was
wondering of the use of the Python GC system has been explored to
control rollback/commit?

The trick used in C++ for this sort of game commonly revolves around
the fact (in C++) that when the scope of a variable is exited, then
the contents of the variable will be destroyed. This approach usually
cuts down on user error and code complexity. We can almost apply this
exact trick in Python!

For example, the original code:

lock(foo)
try:
suite
finally:
unlock(foo)

Could be written (assuming that Python doesn't get too clever too soon
in its GC handling, and local variable optimization):

def do_it(foo):
L = Lock(foo) # Lock() is the constructor for a class
suite

Note that when do_it() exits, there will be no more references to "L",
and hence the instance will be deleted. The delete method (on "L")
can include the unlock activity. (There are probably some interesting
issues of tracebacks holding references to dead scopes and their
contents... but eventually "L" would be __del__'ed).

If this sort of approach is workable, then careful holding of
intermediate results in smart class instance objects might be able to
handle destruction/rollback very nicely. Code might then be
structured as follows... assume suite is:

event1 = lay_foundation()
event2 = build_walls()
event3 = add_roof()

event1.commit()
event2.commit()
event3.commit()

then the code using smart-instances might look like:

def do_stuff():
L = Lock(foo)
E1 = C_R(lay_foundation())
E2 = C_R(build_walls())
E3 = C_R(add_roof())
E1.commit()
E2.commit()
E3.commit()

The idea is that the Commit/Rollback class (called C_R) automatically
calls the rollback on its contents, IF it was not told to commit its
contents before completion. :-) To be very concrete, the class might
be defined as:

class C_R:
def __init__(self, *arg):
self.inards = arg

def commit(self):
for i in self.inards:
if hasattr(i, "commit"):
i.commit()
self.inards = ()

def __del__(self):
for i in self.inards:
if hasattr(i, "rollback"):
i.rollback()
self.inards = ()

...in fact, we could rewrite the do_stuff code as follows:

def do_stuff():
L = Lock(foo)
E1 = C_R(lay_foundation())
E2 = C_R(build_walls(), E1)
E3 = C_R(add_roof(), E2)
E3.commit()

I *think* this sort of code is probably pretty easy to read and write.
Am I still missing something in my view of the problem??

Jim

p.s., I didn't run the code through python... so I'm sure I made some
typos. There should also be some judicious placement of try/except clauses
in the __del__ method for a variety of reasons, and even in the commit
method.

-- 
Jim Roskind
InfoSeek Corporation
voice: 408.982.4469
fax: 408.986.1889
jar@infoseek.com
----------------------------------------------------------------------------
PGP 2.6.1 Key fingerprint =  0E 2A B2 35 01 9B 5C 58  2D 52 05 9A 3D 9B 84 DB 
To get my PGP 2.6 Public Key, "finger -l jar@infoseek.com | pgp -kaf"