При написании кода Common Lisp я использую SLIME. В частности, я компилирую буфер, содержащий определения функций, используя C-C C-k, а затем переключаюсь на REPL для запуска этих функций. Помещение исполняемого кода для запуска этих функций в буфере, похоже, работает не так хорошо. Если в коде есть ошибки, это может привести к путанице.
Было бы удобно иметь способ включить код, который не компилируется в буфер, но запускается из командной строки, например при выполнении
sbcl --script foo.lisp
Если бы это было так, мне не пришлось бы продолжать добавлять и удалять код каждый раз, когда я хотел запустить код из командной строки. Существует ли такое условие?
Это аналог условия Python.
if __name__=='__main__':
, который равен false, если файл Python импортирован как модуль, но равен true, если он запускается как скрипт.
Это сообщение в блоге под названием "Использование 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
.
ОБНОВЛЕНИЕ: Спасибо Всеволоду Демькину за его полезный ответ и продолжение.
Далее следуют некоторые заметки об этом ответе, составленные из комментариев к этому ответу.
@ Всеволод, если ты добавишь это в свой ответ, я их удалю.
Сначала я попросил способ запуска кода из командной строки, но не из интерпретатора.
Поставленное решение делает больше; он также позволяет запускать код из интерпретатора, но не из командной строки.
Первым шагом является определение функции макроса для символа макроса #!
.
Как указано в ссылке «При встрече с макро-символом читатель Lisp вызывает свою макро-функцию читателя».
Функция считывателя определяется вызовом set-dispatch-macro-character
.
Итак, когда символ #!
виден, set-dispatch-macro-character
вызывает лямбда-функцию, определенную в теле, для вызова.
Затем эта функция добавляет ключевое слово :noscript
в переменную *features*
.
Смотрите также обсуждение того, что макросы читателя хороши в вопросе SO
Чтение макросов: для чего вы их используете? .
Обратите внимание, что ключевое слово :noscript
добавляется к *features*
точно, когда присутствует символ #!
. Кроме того, #!
символ присутствует, когда код выполняется внутри интерпретатора, например при использовании slime
, но, по-видимому, отсутствует (удален) из
программы
текст sbcl --script
выполняется. Поэтому :noscript
добавляется к *features*
, когда код запускается в интерпретаторе, но не при запуске как
сценарий.
Теперь мы используем макросы встроенного считывателя #-/#+
, которые, как сказал Всеволод, ведут себя подобно C #IFDEF/#IFNDEF
. Они проверяют на символ
в *features*
. В этом случае #-:noscript
проверяет отсутствие :noscript
, а #+:noscript
проверяет наличие :noscript
.
Если эти условия выполняются, запускается соответствующий код. Чтобы обернуть блок кода, можно использовать
progn
вот так: #-:noscript (progn <your code here>)
.
Наконец, необходимо вызвать 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*
.