#ifndef в Common Lisp
В C, чтобы убедиться, что мы не включаем заголовки, которые мы включили, мы используем следующую структуру:
#ifndef UTILS
#define UTILS
#include "my_utils.h"
#endif
Я разбил свою программу на Лиспе на отдельные файлы; несколько файлов иногда используют один и тот же файл (например, my_utilities используется несколькими файлами). Когда я запускаю программу, я получаю предупреждения о том, что я переопределяю load
одного и того же файла несколько раз).
Это можно исправить, выполнив что-то похожее на #ifndef
в C. Что такое эквивалентный или стандартный метод Common Lisp для этого?
Я довольно новичок в Лиспе. Дайте мне знать, если есть лучшие практики (возможно, другой метод структурирования моих программ?), Которые мне не хватает.
2 ответа
Вопрос, который вы задали
Прямой аналог препроцессорных условий типа #if
в C это #+
средство условного считывания во время чтения.
Вопрос, который вы хотели задать
Чтобы избежать многократной загрузки файла, вы можете использовать стандарт (но не рекомендуется) provide
/ require
средство, или дополнительная система как ASDF.
Для приложений и библиотек Common Lisp предпочтительно использовать инструмент управления системой. Как ASDF или что-то еще, что может обеспечить ваша реализация Система - это набор файлов с зависимостями и различными действиями (загрузка, компиляция,...).
Вы всегда можете проверить состояние среды выполнения и что-то сделать.
Пример:
(unless (fboundp 'foobar)
(require "foo")
(load "bar"))
(unless (find-package 'foobar)
(require "foo")
(load "bar"))
PROVIDE
а такжеREQUIRE
встроенные функции именно для этого. Если вам нужен модуль, он будет загружен, если ужеprovided
, К сожалению, эта функциональность недостаточно указана в стандарте, но реализации могут предоставлять полезную функциональность.Стандартные среды выполнения Lisp имеют список функций в списке
*features*
, Вы можете использовать это для рекламы и проверки функциональности.
Пример:
В вашей библиотеке:
(push :cool-new-graphics-library cl:*features*)
В вашем коде приложения:
(when (member :cool-new-graphics-library cl:*features*)
(funcall (find-symbol "DRAW-SPACE-SHIP" "CNGL")
:death-star))
Common Lisp предоставляет способ обусловить время чтения. Следующий код будет прочитан только когда :cool-new-graphics-library
функция присутствует, и, следовательно, только тогда она будет выполнена позже:
#+cool-new-graphics-library(cngl:draw-space-ship :death-star)
Common Lisp также позволяет вам выразить некоторую логику:
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
Обратите внимание, что вы можете заставить Lisp выполнять код во время компиляции:
(eval-when (:load-toplevel :compile-toplevel :execute)
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
)
Для этого работать EVAL-WHEN
должен быть на верхнем уровне в файле. Это означает, что он не будет работать глубоко во вложенных формах. Это работает внутри верхнего уровня PROGN
,LOCALLY
, MACROLET
а также SYMBOL-MACROLET
, хоть.
таким образом EVAL-WHEN
позволяет запускать код, который является частью файла, который в данный момент компилируется. Этот код, чем может искать загруженные системы, предоставленные модули, доступные функции и многое другое.