(write the-data (open-output-file "data.scm")) ? =)
Generally though, you're better off with with-input-file and with-output-file , as the return of the thunk communicated explicitly to Gambit's IO system, that the port is no longer used, i.e. (with-input-from-file "data.scm" read) / (with-output-to-file "data.scm" (lambda (p) (write your-data p))).
Also of course you could do (let* ((p (open-input-file "data.scm")) (d (read p))) (close-port p) d) , but you see it's less concise. (Also, what if read would throw an exception, clearly this variant does not come with any finalization of p - would with-intput-from/to-file finalize them? - anyone is free to clarify this.)
Just dropping the file handle will wait for it to garbage-collect away, which generally is really fine but potentially could bring problems (say that you'd unintentionally do 10 000 file operations like that prior to a GC, that would generally cause the OS to run out of file descriptors and you'd get more or less weird error messages).
Also note that with this kind of very high level resources, you cannot expect them to be automatically GC:ed away. Thread objects for instance, at least if they're running, are not GC:ed away. With file ports, I'd believe they are. With TCP ports, not clear. Anyone is free to bring clarity to this one too.