Common Lisp 中的#ifndef

#ifndef in Common Lisp

在 C 中,为确保我们不包含 re-include headers,我们使用以下结构:

#ifndef UTILS
#define UTILS

#include "my_utils.h"

#endif

我已经把我的 Lisp 程序分解成单独的文件;多个文件有时会使用同一个文件(例如,my_utilities 被多个文件使用)。当我 运行 程序时,我收到警告说我正在重新定义事物(多次调用同一文件的 load )。

这可以通过在 C 中执行类似于 #ifndef 的操作来解决。执行此操作的 Common Lisp 等效方法或标准方法是什么?

我对 Lisp 还很陌生。让我知道是否有我缺少的最佳实践(也许是另一种构建程序的方法?)。

你问的问题

预处理器条件的直接模拟,如 C 中的 #if#+ 读取时条件化工具。

您想问的问题

为避免多次加载文件,您可以使用标准 (但已弃用) provide/require 设施, 或者像 ASDF.

这样的附加系统
  1. 对于 Common Lisp 应用程序和库,最好使用 系统 管理工具。像 ASDF 或您的实施可能提供的任何东西。系统是具有依赖关系和各种操作(加载、编译...)的文件的集合。

  2. 您可以随时检查 运行时间的状态并做一些事情。

示例:

(unless (fboundp 'foobar)
  (require "foo")
  (load "bar"))

(unless (find-package 'foobar)
  (require "foo")
  (load "bar"))
  1. PROVIDEREQUIRE 正是用于此目的的内置函数。如果你需要一个 模块 它将被加载,除非已经 provided。不幸的是,此功能在标准中未指定,但实现可能会提供有用的功能。

  2. Common 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 必须位于文件的顶层。这意味着它不会在嵌套表单中深入工作。不过,它确实在顶层 PROGNLOCALLYMACROLETSYMBOL-MACROLET 中工作。

因此 EVAL-WHEN 允许您 运行 代码是当前编译文件的一部分。这段代码可以查找加载的系统、提供的模块、可用的函数等等。