If you want X, you know where to find it (was Re: do...until wisdom needed...)

Jeff Epler jepler at inetnebr.com
Sat Apr 21 21:34:55 EDT 2001


On 18 Apr 2001 01:27:37 -0400, Douglas Alan
 <nessus at mit.edu> wrote:
> Well, yes, you could use a procedural macro (hygienic, or otherwise)
> to convert Pascal code to Python, but it would be one really big hairy
> macro, and I don't think that be a good idea.  More modestly, you
> might define two macros, "let" and "set" so that
> 
>    let x = 3
> 
> gets translated into
> 
>    try:
>       x
>       raise VariableAlreadyBound("x")
>    except NameError:
>       x = 3  
> 
> and
> 
>    set x = 3
> 
> gets tranlated into
> 
>    try:
>      x
>      x = 3
>    except NameError:
>       raise VariableNotBound("x")

This particular example can be done with very nearly the same syntax in
standard Python---a dot instead of whitespace between let/set and the
variable in question.

>>> import letset, __main__; letset.setup(__main__)
>>> let.x = 3
>>> x
3
>>> let.x = 4
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "getset.py", line 10, in __setattr__
    raise VariableAlreadyBound(attr)
getset.VariableAlreadyBound: x
>>> set.y = 5
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "getset.py", line 20, in __setattr__
    raise VariableNotBound(attr)
getset.VariableNotBound: y
>>> set.x = 6
>>> print x
6

(letset is also suitable for use in a class, though the syntax becomes a bit
odder:
>>> class C:
...     def __init__(self, arg):
...             letset.setup(self)
...             self.let.x = arg
...
>>> y = C(4)
>>> y.x
4

let.self.x won't work for reasons that should be obvious after a moment's
thought)

In function context, 'set.x=...' provides a nice replacement for
'global x; x=...', I'm inclined to think.

Jeff Epler
jepler at inetnebr.com

#--- letset.py ----------------------------------------------------------
class VariableAlreadyBound(Exception): pass
class VariableNotBound(Exception): pass

class Let:
    def __init__(self, namespace):
	self.__dict__['_Let__n'] = namespace

    def __setattr__(self, attr, val):
	if hasattr(self.__n, attr):
	    raise VariableAlreadyBound(attr)
	setattr(self.__n, attr, val)

class Set:
    def __init__(self, namespace):
	self.__dict__['_Set__n'] = namespace

    def __setattr__(self, attr, val):
	if not hasattr(self.__n, attr):
	    raise VariableNotBound(attr)
	setattr(self.__n, attr, val)

def setup(namespace):
    setattr(namespace, "let", Let(namespace))
    setattr(namespace, "set", Set(namespace))
    
#------------------------------------------------------------------------



More information about the Python-list mailing list