I'm learning CL, and I have minimal experience in other languages. Could someone explain to me in layman terms what this means, especially what "out" here represents, and how it all fits together:
(defun save-db (filename)
(with-open-file (out filename
:direction :output
:if-exists :supersede)
(with-standard-io-syntax
(print *db* out))))
Mostly, the bit I don't understand is "out", but an explanation of the whole thing would be nice.
Thanks
An open file format is a file format for storing digital data, defined by an openly published specification usually maintained by a standards organization, and which can be used and implemented by anyone. Open file format is licensed with open license.
The open() function opens a file, and returns it as a file object.
From the desktop, right-click the desired file. From the drop-down menu, click Open with, then select the desired application. In this example, we'll select Paint. The file will open in the selected application.
Thus, with statement helps avoiding bugs and leaks by ensuring that a resource is properly released when the code using the resource is completely executed. The with statement is popularly used with file streams, as shown above and with Locks, sockets, subprocesses and telnets etc.
Using open() we can use the file handler as long as the file has not been explicitly closed using file_handler. close(), but in case of using with open() context manager, we cannot use a file handler outside the with block. It will raise ValueError: I/O operation on closed file in that case.
out is the stream variable bound to the open file. with-open-file guarantees that the file is open inside the scope, and closed outside the scope, no matter how you exit.
As an addition to ddyer, you can also use MACROEXPAND
or MACROEXPAND-1
to see what WITH-OPEN-FILE
does:
(macroexpand '(with-open-file (out filename
:direction :output
:if-exists :supersede)
(with-standard-io-syntax
(print *db* out))))
tells us
(LET ((OUT (OPEN FILENAME :DIRECTION :OUTPUT :IF-EXISTS :SUPERSEDE)) (#:G748 T))
(UNWIND-PROTECT
(MULTIPLE-VALUE-PROG1 (PROGN (WITH-STANDARD-IO-SYNTAX (PRINT *DB* OUT)))
(SETQ #:G748 NIL))
(WHEN OUT (CLOSE OUT :ABORT #:G748))))
We can see that we open the file called filename
and assign that open file stream to out
, and do something. Should something bad happen, UNWIND-PROTECT
will CLOSE
the stream, should it be non-nil
.
The #:G748
variable is a GENSYM
ed symbol (so it's a fresh, uninterned, symbol). If nothing goes wrong writing the file, we set #:G748
to nil
.
Thus, when we CLOSE
the stream, if something went wrong #:G748
will be T
, so CLOSE
will attempt to clean up any side effects of having created the stream.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With