В дополнение к ddyer, вы также можете использовать MACROEXPAND
или MACROEXPAND-1
, чтобы увидеть, что WITH-OPEN-FILE
делает:
(macroexpand '(with-open-file (out filename
:direction :output
:if-exists :supersede)
(with-standard-io-syntax
(print *db* out))))
говорит нам
(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))))
Мы можемувидим, что мы открываем файл с именем filename
, назначаем поток открытых файлов на out
и что-то делаем.Если случится что-то плохое, UNWIND-PROTECT
будет CLOSE
потоком, если он не будет nil
.
Переменная #:G748
является символом GENSYM
ed (так что это свежий, непереданный,условное обозначение).Если при записи файла ничего не происходит неправильно, мы устанавливаем #:G748
в nil
.
Таким образом, когда мы CLOSE
в потоке, если что-то пошло не так, #:G748
будет T
, поэтому CLOSE
будет пытаться убрать любые побочные эффекты создания потока.