nowlin@iwtqg.att.com (01/18/91)
> Subject: Overcoming inelegance? > > Many times I've encountered the following problem: I have a procedure *p* > that each time it's called writes some material to a file *f*. I want to > pass *f* as a command-line parameter and close *f* when I'm done. There > are two inelegant ways to do this: > > (1) Make the file name a global variable; open and close it outside of *p*. > > (2) Jigger the parameters passed to *p* so that a special form of argument > indicates file opening or closing rather than data to be written. > > Is there an elegant way? (A similar problem exists for input.) > > Paul Abrahams > abrahams%wayne-mts@um.cc.umich.edu A compromise to the global variable is to pass an opened file pointer into the procedure p(). Just open the file outside the procedure and close it after the last time the procedure is called. The ability to have the entire open(), write(), close() suite of calls contained in the procedure is tricky. The procedure then has to know the file name somehow. The real problem I see with the self-contained approach is the same one that was batted around when the discussion of a "final" clause was going on. How do you know when it's the last time you're calling a procedure? In this special case you should be able to rely on the language itself or the underlying operating system to flush all buffers and close all opened files as a program terminates. Then you only need to worry about opening the file. Is the following the kind of idea you had? The comment explains the concept: procedure main(args) p("first output") every f := !args do every p(1 to 10,f) p("last output") end # This procedure writes the data 'd' to an output stream. 'f' is optional # but if passed it's assumed to be a file name and is checked against the # currently open file. If they're the same continue writing to the open # file. If they're different close the current file and open the new one. # If no file is ever passed all writing is to standard output. NOTE: It is # assumed that the system itself will flush and close the final file opened. procedure p(d,f) static o initial o := &null if \f & not (image(o) ? (="file(" & f == tab(upto(')')))) then { if image(o) ? ="file(" then close(o) o := open(f,"w") | stop("can't open: ",f) } write(o,d) return end Realize, I don't like the idea of relying on the system to close files for me. That's sloppy not elegant. Maybe someone will come up with a better idea. Jerry Nowlin att!iwtqg!nowlin