以编程方式加载 Common Lisp 模块 软件包和系统的快速总结你的问题

问题描述

几周前我刚刚开始学习 Common Lisp,如果这是一个明显的问题,很抱歉。如何以编程方式加载模块?我有一个“任务”目录,每个都是一个 Lisp 程序,我想导入每个任务并运行它们都包含的特定函数

我找到了一种遍历目录的方法(通过 UIOP:DIRECTORY-FILES)。但是我一直在想办法将模块“作为”特定名称加载,就像在 Python 中一样。这将允许我在循环中 load "module-1.lisp" as modload "module-2.lisp" as mod

代码

for path in directory
    (load path as mod)
    (mod:function)

如果有更好的方法来实现我想要做的事情,请随时说出来!在此先感谢您的帮助!

解决方法

软件包和系统的快速总结

“加载为” 在 Common Lisp 中没有意义,因为加载与定义新系统或包不同。在 Python 中,文件是模块等,但在 Lisp 中不是。

Lisp 有一个的概念,它们是命名空间。它们用于组织符号(符号是一流的值)。换句话说,他们使用、导出或从其他包中导出或隐藏符号,仅此而已。当您计算 (in-package pack) 时,您可以直接从 pack 编写所有 accessible 符号,例如 my-fun,否则您需要完全限定符号,例如 {{1} }. 有一些扩展允许您导入具有不同名称的包,但这不是标准的(请参阅 https://github.com/phoe/trivial-package-local-nicknames

加载 Lisp 脚本不一定与定义包相同,它取决于文件中的内容(如果它是 some-package:their-func 形式)。

当您想在 Lisp 中组织源代码时,您可以使用 ASDF 定义一个系统。系统列出了它的所有依赖项、它的组件(文件)以及它们的组件之间的依赖项。这就是您描述文件应该以何种顺序加载、编译、测试等的方式。

包和系统是独立的,但在小型系统中,您通常对系统具有相同的名称及其定义的唯一包。对于较大的系统,可能有多个包。

21. Programming in the Large: Packages and Symbols

你的问题

你的每个文件都需要定义一个包,以避免污染单个命名空间,例如:

defpackage

但是一旦它们全部加载完毕,无论是使用您的方法还是定义适当的 ASDF 系统,您都希望能够访问所有包中的所有 (defpackage :common-name.01 (:use :cl :utils) (:export #:run-me)) (in-package :common-name.01) ;; some code 函数。

您可以编写一些列出包等的内省代码,但我认为更好的方法是让您的每个文件都有一种方法声明它们的 RUN-ME 函数应该在您的框架中注册,就像测试框架一样。

例如,在文件末尾,您可以这样写:

RUN-ME

这假设例如您的 (provide-function 'run-me) 包定义并导出名为 utils 的函数,该函数将值存储在中央注册表中。

例如,在 provide-function 中:

utils.lisp

当你想运行所有函数时,你可以遍历这个列表:

(defpackage :utils
   (:use :cl) 
   (:export #:provide-function
            #:run-all))

(in-package :utils)

(defvar *all-interesting-functions* nil)

(defun provide-function (f)
  (pushnew f *all-interesting-functions* :test #'eql))