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