From: Jack Vinson
Subject: multiple use of with-open-file, or with-open-stream
Date: 
Message-ID: <45084@netnews.upenn.edu>
Hello again lisp.hackers,

I am reading a bunch of data into lisp from a number of files which isn't that
big of a deal, I can simply nest several with-open-file's.  The problem occurs
when I do not know, a priori, the number of data files from which I will be
reading.  i.e. That number is read in as well.

Is there some way (a macro?) that I can get the functionality of with-open-file
and with-open-stream without initially knowing how many files (or stream) I
will have initially?  My current solution is to open all the files, run the
body of the program, and then close everything.  This is fine, until my program
bombs (and it's kinda large) and I have to remember to close out all the
streams by hand.


Jack Vinson				······@linc.cis.upenn.edu

From: Peter Benson
Subject: Re: multiple use of with-open-file, or with-open-stream
Date: 
Message-ID: <PAB.91Jun24111117@challenger.lucid.com>
You should use this idiom:

(let ((abort t)
      (list-of-file-to-open (find-files-to-open))
      (list-of-streams-to-close ()))
  (unwind-protect
      (progn 
        (dolist (file list-of-files-to-open)
          (push (open-my-file file) list-of-streams-to-close))
        (do-stuff-with-streams list-of-streams-to-close)
        (setq abort nil))
    (dolist (stream list-of-streams-to-close)
      (close stream :abort abort))))

If you bomb out in the middle of do-stuff-with-streams then all the files
will be closed properly.

If you macroexpand with-open-file you will find that it uses the same idiom
only with one file and stream.
From: Bruce R. Miller
Subject: Re: multiple use of with-open-file, or with-open-stream
Date: 
Message-ID: <2886773477@ARTEMIS.cam.nist.gov>
In article <·····@netnews.upenn.edu>, Jack Vinson writes: 
> 
> Hello again lisp.hackers,
> 
> I am reading a bunch of data into lisp from a number of files which isn't that
> big of a deal, I can simply nest several with-open-file's.  The problem occurs
> when I do not know, a priori, the number of data files from which I will be
> reading.  i.e. That number is read in as well.
> 
> Is there some way (a macro?) that I can get the functionality of with-open-file
> and with-open-stream without initially knowing how many files (or stream) I
> will have initially?  My current solution is to open all the files, run the
> body of the program, and then close everything.  This is fine, until my program
> bombs (and it's kinda large) and I have to remember to close out all the
> streams by hand.
> 
> 
> Jack Vinson				······@linc.cis.upenn.edu

It's not too clear what you're doing with all those files, but I'll try
to offer some alternatives.
  You seem to want them all open while the program is running. Could you
alternatively, read them one at a time into some sort of data structure?

  Otherwise, you could use recursion; recurse until all files are open
then within that do whatever you want.  But what do you do with the
streams, though? collect them into a list? If so, then consider:

  with-open-file/stream use an unwind-protect to achieve the
automatic closing.  You also could use unwind-protect; within the
`protected-form' you would loop, open each file, collect the streams
into a list.  then do whatever you want with the streams. The
`cleanup-forms' would loop through opened streams and close them.

bruce
······@cam.nist.gov
From: Peter L. DeWolf
Subject: Re: multiple use of with-open-file, or with-open-stream
Date: 
Message-ID: <PLD.91Jun24130012@whopper.lcs.mit.edu>
> Is there some way (a macro?) that I can get the functionality of
> with-open-file and with-open-stream without initially knowing how many
> files (or stream) I will have initially?  My current solution is to
> open all the files, run the body of the program, and then close
> everything.  This is fine, until my program bombs (and it's kinda
> large) and I have to remember to close out all the streams by hand.

The primitive used by (with-open-file) to close things in the face of
errors is (unwind-protect).  That's easy enough to use.  Here's a
trivial function that opens an arbitrary number of files and causes an
error.  It automatically closes the files even if you abort out of the
error.

(defun open-many-files (&rest files)
  (let ((streams nil))
    (unwind-protect
      (progn
        (dolist (file files)
          (push (open file) streams))
        (error "Too bad"))
     ;;Here's the cleanup form.  Close all the files...
     (dolist (stream streams)
       (close stream)))))

 - Peter
--

   Peter L. DeWolf
   Motorola Cambridge Research Center
   ···@mcrc.mot.com -or- ···@abp.lcs.mit.edu