Why don't people like lisp?
Brian Kelley
bkelley at wi.mit.edu
Thu Oct 23 10:53:21 EDT 2003
Matthew Danish wrote:
> On Wed, Oct 22, 2003 at 12:30:01PM -0400, Brian Kelley wrote:
>
>>Your two examples do completely different things and the second is
>>written rather poorly as f might might not exist in the finally block.
>>It certainly won't if the file doesn't exist.
>>
>>A better comparison would (*might*, I haven't used lisp in a while) be:
>>
>>(with-open-file (f filename :direction :output :if-exists :supersede)
>> (format f "Here are a couple~%of test data lines~%")) => NIL
>>
>>if os.path.exists(filename):
>> f = open(filename, 'w')
>> print >> f, "Here are a couple of test data lines"
>
>
> How are these in any way equivalent? Pascal posted his example with
> try...finally and f.close () for a specific reason. In your Python
> example, the file is not closed until presumably the GC collects the
> descriptor and runs some finalizer (if that is even the case).
The file is closed when the reference count goes to zero, in this case
when it goes out of scope. This has nothing to do with the garbage
collector, just the reference counter. At least, that's the way I
understand, and I have been wrong before(tm). The upshot is that it has
worked in my experience 100% of the time and my code is structured to
use (abuse?) this. How is this more difficult?
The difference here, as I see it, is that if an exception happens then
the system has to wait for the garbage collector to close the file. In
both examples there was no exception handling after the fact (after the
file is closed). The macro, then, allows execution to continue with the
closed file while the python version stops execution in which case the
file is closed anyway. (unless it is in a another thread of execution
in which the file is closed when it goes out of scope)
In either case one still needs to write handling code to support the
failure as this is most likely application specific. Using macros as a
default handler seems very appropriate in lisp. In python, as I
mentioned in the model-centric view I would create a new file object to
support better handling of file-i/o and failures and hence abstract away
the "error-prone" styles you mentioned.
Now, macros really shine when they also use the local scope. However,
unless a macro is actually doing this I see no real difference between
creating a wrapper for an object and a macro:
f = FileSafeWrapper(open(...))
(with-file-open (f ...)
Except that the macros you are describing are part of the common
distribution. I have to write my own FileSafeWrapper for now...
> http://www.lispworks.com/reference/HyperSpec/Body/m_w_open.htm#with-open-file
>
> So in fact, you pointed out a bug in Pascal's Python example, and one
> that is easy to make. All this error-prone code is abstracted away by
> WITH-OPEN-FILE in Lisp.
This is a good thing, naturally. But the examples you have given are
completely do-able (in one form or another) in python as it currently
stands, either by creating a wrapper around a file object that can
properly close down on errors or what not. In fact, this might be a
better abstraction in some cases. Consider:
(with-file-that-also-outputs-to-gui ... )
(with-file-that-also-outputs-to-console ...)
to
(with-open-file (f ...
in this case, f is supplied by some constructor that wraps the file to
output to the gui or standard i/o and is passed around to various
functions. Which is the better solution?
I'm not saying that lisp can't do this, it obviously can, but macros
might not be the appropriate solution to this problem ( they certainly
aren't in python ;) )
p.s. I really do enjoy programming in lisp, it was my second programming
language after fortran 77.
More information about the Python-list
mailing list