include - compiler - #ifndef en Common Lisp
clisp windows (2)
La pregunta que hiciste
El análogo directo de las condiciones del preprocesador como #if
en C es la facilidad de condicionalización #+
tiempo de lectura.
La pregunta que querías preguntar
Para evitar la carga múltiple de un archivo, puede usar el recurso estándar / obsoleto de provide
/ require
, o un sistema complementario como ASDF .
En C, para asegurarnos de no volver a incluir los encabezados incluidos, utilizamos la siguiente estructura:
#ifndef UTILS
#define UTILS
#include "my_utils.h"
#endif
Rompí mi programa Lisp en archivos separados; varios archivos a veces usan el mismo archivo (p. ej., my_utilities es utilizado por varios archivos). Cuando ejecuto el programa, recibo advertencias de que estoy redefiniendo cosas (llamando a la load
del mismo archivo varias veces).
Esto se solucionaría haciendo algo similar a #ifndef
en C. ¿Cuál es el método Common Blip equivalente o estándar para hacer esto?
Soy bastante nuevo para Lisp. Avíseme si hay mejores prácticas (tal vez, un método diferente de estructurar mis programas) que me falta.
Para las aplicaciones y bibliotecas Common Lisp, se prefiere usar una herramienta de administración del sistema . Como ASDF o lo que sea que su implementación pueda proporcionar. Un sistema es una colección de archivos con dependencias y varias acciones (cargar, compilar, ...).
Siempre puedes verificar el estado del tiempo de ejecución y hacer algo.
Ejemplo:
(unless (fboundp ''foobar)
(require "foo")
(load "bar"))
(unless (find-package ''foobar)
(require "foo")
(load "bar"))
PROVIDE
yREQUIRE
son funciones integradas para eso exactamente. Si necesita un módulo , se cargará, a menos que ya se hayaprovided
. Desafortunadamente, esta funcionalidad no está especificada en el estándar, pero las implementaciones pueden proporcionar una funcionalidad útil.Los tiempos de ejecución de Common Lisp tienen una lista de características en la lista
*features*
. Puede usar eso para publicitar y verificar la funcionalidad.
Ejemplo:
En tu biblioteca:
(push :cool-new-graphics-library cl:*features*)
En tu código de aplicación:
(when (member :cool-new-graphics-library cl:*features*)
(funcall (find-symbol "DRAW-SPACE-SHIP" "CNGL")
:death-star))
Common Lisp proporciona una forma de condicionalizar ese tiempo de lectura . El siguiente código solo se leerá cuando esté presente la función :cool-new-graphics-library
, y solo así se ejecutará más adelante:
#+cool-new-graphics-library(cngl:draw-space-ship :death-star)
Common Lisp también te permite expresar algo de lógica:
#+(and lispworks cool-new-graphics-library)
(cngl:draw-space-ship :enterprise)
#-cool-new-graphics-library(warn "no cool graphics library available")
Tenga en cuenta que puede forzar a Lisp a ejecutar código en tiempo de compilación:
(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")
)
Para que esto funcione, EVAL-WHEN
tiene que estar en el topevel de un archivo. Eso significa que no funcionará en profundidad en formas anidadas. Sin embargo, funciona dentro de un nivel PROGN
, LOCALLY
, MACROLET
y SYMBOL-MACROLET
.
Por lo tanto, EVAL-WHEN
permite ejecutar código que es parte del archivo que se compila actualmente. Este código puede buscar sistemas cargados, módulos proporcionados, funciones disponibles y más.