Python syntax in Lisp and Scheme
Daniel P. M. Silva
dsilva at ccs.neu.edu
Wed Oct 8 12:50:39 EDT 2003
<posted & mailed>
Alex Martelli wrote:
> Daniel P. M. Silva wrote:
> ...
>> You still can't add new binding constructs or safe parameterizations like
>> a with_directory form:
>>
>> with_directory("/tmp", do_something())
>>
>> Where do_something() would be evaluated with the current directory set to
>> " tmp" and the old pwd would be restored afterward (even in the event of
>> an exception).
>
> Right: you need to code this very differently, namely:
> with_directory("/tmp", do_something)
> *deferring* the call to do_something to within the with_directory
> function. Python uses strict evaluation order, so if and when you
> choose to explicitly CALL do_something() it gets called,
>
> So, I would code:
>
> def with_directory(thedir, thefunc, *args, **kwds):
> pwd = os.getcwd()
> try: return thefunc(*args, **kwds)
> finally: os.chdir(pwd)
>
> this is of course a widespread idiom in Python, e.g. see
> unittest.TestCase.assertRaises for example.
>
> The only annoyance here is that there is no good 'literal' form for
> a code block (Python's lambda is too puny to count as such), so you
> do have to *name* the 'thefunc' argument (with a 'def' statement --
> Python firmly separates statements from expressions).
That was my point. You have to pass a callable object to with_directory,
plus you have to save in that object any variables you might want to use,
when you'd rather say:
x = 7
with_directory("/tmp",
print "well, now I'm in ", os.getpwd()
print "x: ", x
x = 3
)
>> Last year -- I think at LL2 -- someone showed how they added some sort of
>> 'using "filename":' form to Python... by hacking the interpreter.
>
> A "using" statement (which would take a specialized object, surely not
> a string, and call the object's entry/normal-exit/abnormal-exit methods)
> might often be a good alternative to try/finally (which makes no provision
> for 'entry', i.e. setting up, and draws no distinction between normal
> and abnormal 'exits' -- often one doesn't care, but sometimes yes). On
> this, I've seen some consensus on python-dev; but not (yet?) enough on
> the details. Consensus is culturally important, even though in the end
> Guido decides: we are keen to ensure we all keep using the same language,
> rather than ever fragmenting it into incompatible dialects.
The point is that the language spec itself is changed (along with the
interpreter in C!) to add that statement. I would be happier if I could
write syntax extensions myself, in Python, and if those extensions worked
on CPython, Jython, Python.Net, Spy, etc.
>
>
>> Some people use Python's hooks to create little languages inside Python
>> (eg. to change the meaning of instantiation), which are not free of
>> problems:
>>
>> class Object(object):
>> def __init__(this, *args, **kwargs):
>
> [invariably spelt as 'self', not 'this', but that's another issue]
>
>> this.rest = args
>> this.keys = kwargs
>>
>> def new_obj_id(count=[0]):
>> count[0] = count[0] + 1
>> return count[0]
>>
>> def tag_obj(obj, id):
>> obj.object_id = id
>> return obj
>>
>> def obj_id(obj): return obj.object_id
>>
>> type.__setattr__(Object, "__new__", staticmethod(lambda type, *args:
>> tag_obj(object.__new__(type), new_obj_id())))
> ...
>> # forgot to check for this case...
>> print Object(foo="bar")
>
> It's not an issue of "checking": you have written (in very obscure
> and unreadable fashion) a callable which you want to accept (and
> ignore) keyword arguments, but have coded it in such a way that it
> in fact refuses keyword arguments. Just add the **kwds after the
> *args. This bug is not really related to "little languages" at all:
> you might forget to specify arguments which you do want your callable
> to accept and ignore in a wide variety of other contexts, too.
I think changing the meaning of __new__ is a pretty big language
modification...
- Daniel
More information about the Python-list
mailing list