При написании кода на Common Lisp я использую SLIME. В частности, я компилирую буфер, содержащий определения функций, используя C-C C-k, а затем переключаюсь на REPL для запуска этих функций. Размещение исполняемого кода для запуска этих функций в буфере не работает так хорошо. Если в коде есть ошибки, это может привести к беспорядку.
Было бы удобно иметь возможность включать код, который не компилируется в буфере, а запускается из командной строки, например при выполнении
sbcl --script foo.lisp
Если бы это было так, мне не пришлось бы добавлять и удалять код каждый раз, когда я хочу запустить код из командной строки. Существует ли такое условие?
Это аналогично условию Питона.
if __name__=='__main__':
что неверно, если файл Python импортируется как модуль, но верно, если он запускается как скрипт.
Этот пост в блоге, озаглавленный «Использование SBCL для сценариев оболочки Common Lisp», найденный случайным поиском в Google, содержит
;; If run from command line, the following if-test will succeed
(if (> (length sb-ext:*posix-argv*) 1)
;; Code that is executed from the command line only goes here
)
Включенный код действительно не запускается компилятором внутри SLIME, но он не также не запускается с помощью sbcl --script
.
ОБНОВЛЕНИЕ: Спасибо Всеволоду Демкину за полезный ответ и дополнения. Далее следуют некоторые примечания об этом ответе, составленные из комментариев к этому ответу. @Всеволод, если ты добавишь это в свой ответ, я их удалю.
Во-первых, я попросил способ запускать код из командной строки, а не из интерпретатора. Поставляемое решение делает больше; это также дает возможность запускать код из интерпретатора, но не из командной строки.
Первым шагом является определение макрофункции чтениядля символа макроса #!
.
Как указано в ссылке «При встрече с символом макроса программа чтения Лиспа вызывает свою макрофункцию чтения».
Функция чтения определяется вызовомset-dispatch-macro-character
.
Итак, когда #!
символ set-dispatch-macro-character
вызывает лямбда-функцию, определенную в теле.
Затем эта функция добавляет ключевое слово :noscript
к переменной*features*
.
См. также обсуждение того, для чего хороши макросы чтения в вопросе SO.
Макросы чтения: для чего вы их используете?.
Обратите внимание, что ключевое слово :noscript
добавляется к *features*
именно тогда, когда #!
присутствует символ. Кроме того, #!
символ присутствует, когда код запускается внутри интерпретатора, например. при использовании слизи
, но видимо отсутствует (удален) из программы
text by sbcl --script
запускается. Поэтому :noscript
добавляется к *features*
, когда код запускается в интерпретаторе, но не при запуске как
сценарий.
Теперь мы используем встроенные макросы чтения #-/#+
, которые, как сказал Всеволод, ведут себя аналогично #IFDEF/#IFNDEF
в языке C.Они проверяют символ
в *функции*
. В этом случае #-:noscript
проверяет отсутствие :noscript
, а #+:noscript
проверяет наличие :noscript
.
Если эти условия выполняются, он запускает соответствующий код. Чтобы обернуть блок кода, можно использовать
progn
вот так: #-:noscript (progn )
.
Наконец, необходимо вызвать set-dispatch-macro-character
перед запуском кода, использующего эту функциональность. В случае sbcl
можно положить
это в файле инициализации ~/.sbclrc
. Обратите внимание, что этот подход не зависит от того, является ли реализация Common Lisp SBCL.
Более простой альтернативой, упомянутой в списке sbcl-devel, является использование ключевого слова :SWANK
при вводе *features*
в
.
REPL внутри emacs с использованием SLIME. SWANK — это серверная часть SLIME. SLIME, вероятно, правильнее называть SLIME/SWANK, так как эти два
клиент-серверные компоненты клиент-серверной архитектуры. Я нашел это сообщение в блоге под названием Понимание
SLIME, что было полезно.
Таким образом, можно использовать #-:swank
и #+:swank
так же, как #-:noscript
и #+:noscript
, за исключением того, что не нужно писать никакого кода.Конечно, это не сработает, если вы используете интерпретатор командной строки sbcl
, например,
с тех пор :SWANK
не будет отображаться в *features*
.