1

我必须用 Lisp 写一个游戏。为了清楚起见,我想将代码拆分为不同的 .lisp 文件。

如何从另一个文件中的函数中调用函数?

例如,file1.lisp 有一个名为 function1 的函数,而 file2.lisp 有一个名为 function2 的函数。如何从函数 1 中调用函数 2?

谢谢!

4

4 回答 4

5

正如你所知,有多种不同的 Lisp 系统。我将发布 Common Lisp 的答案。

天真的方法是使用(load "filename.lisp"),但一段时间后它并不能很好地工作。所以...

Common Lisp 有一个名为“ASDF”的库,用于处理打包和文件管理。ASDF 有一些设置。

  1. 创建 ASDF 查找文件的目录。
  2. 将此信息添加到我的 Lisp 系统的 init 文件中。

我在我的.sbclrc文件中使用它(假设我在 ~ 中创建了一个 .asdf 文件):

(pushnew "~/.asdf/" asdf:*central-registry* :test #'equal)

我通常使用以前构建的 ASDF 文件,然后对其进行修改。

这是一个示例 ASDF 文件的内容:

(asdf:defsystem #:cl-linq
  :depends-on ( #:alexandria #:anaphora)
  :components ((:file "cl-linq"))
  :name "cl-linq"
  :version "0.1"
  :maintainer "Paul Nathan"
  :author "Paul Nathan"
  :licence "LLGPL"
  :description "CL LINQ style interface with strains of SQL"
  :long-description
  "DSL for managing and querying datasets in a SQL/LINQ style
syntax. cl-linq provides a simple and usable set of primitives to
make data examination straightforward. ")

我将此代码放在cl-linq.asd源代码旁边的文件中(cl-linq.lisp 来自"cl-linq"defsystem 中的组件),然后将cl-linq.asd文件符号链接到我的~/.asdf/目录。

在我的 cl-linq.lisp 文件中,我包含以下内容:

(defpackage :cl-linq
  (:use
   :common-lisp
   :anaphora)
  (:export
   #:query
   #:cl-linq-select))
(in-package :cl-linq)

因此,对于您的情况,我将有 2 个组件;每个都有自己的 defpackage 形式,将其他包需要的功能导出。

对于示例,我从我的一个项目CL-LINQ中获取了代码。您可以完全自由地将其用作模板。

于 2013-11-01T17:22:35.963 回答
1

这适用于 Emacs Lisp(又名 elisp)

在此位置创建文件: ~/.emacs.d/init.el

在此位置创建文件: ~/.emacs.d/file1.el

在此位置创建文件: ~/.emacs.d/file2.el

现在,打开~/.emacs.d/init.el并写入(然后保存):

(load "~/.emacs.d/file1.el")

(load "~/.emacs.d/file2.el")

(defun run-both-functions ()
  (interactive)
    (switch-to-buffer "*Messages*")
    (first-function)
    (sit-for 2)
    (second-function))

现在,打开~/.emacs.d/file1.el并写入(然后保存):

(defun first-function ()
    (message "My name is Fred."))

现在,打开~/.emacs.d/file2.el并写入(然后保存):

(defun second-function ()
    (message "My name is George."))

现在,重新启动 Emacs 并输入: M-x run-both-functions RET

您放入上述三 (3) 个文件中的任何一个的任何功能都可以被其他功能访问。您会注意到其中run-both-functions包含一个(interactive)语句,这意味着用户可以使用M-x键盘快捷键或键盘快捷键调用该函数。

于 2013-11-02T15:13:29.037 回答
0

如果您使用函数加载,则不指定文件类型会很有用。

加载文件:fasl 或 source

而不是(load "foo.lisp")一个可以调用(load "foo")。通常,Common Lisp 提供将 Lisp 文件编译为fasl快速加载)文件的功能。这些通常是预编译的字节码本机代码。通常,如果存在文件,Common Lisp 实现将加载已编译的代码。这样可以节省时间(因为编译后的代码通常可以比 Lisp 源代码更快地加载)并且代码通常更快(因为文件编译器已经编译了它)。

如果编译文件较新,通常使用函数加载编译文件,或者首先将源文件编译为新的编译文件。

根据正在加载的当前文件加载文件

(load "foo")文件foo中不是一个完整的文件名。例如,我们不知道加载它的目录。这取决于*default-pathname-defaults*当前目录的值或在某些实现中的值(对于 Unix 系统是典型的)。根据我们当前正在加载的文件加载文件可能很有用 - 如果加载一个文件会触发更多文件被加载。对于这个 Common Lisp 有变量*load-pathname**load-truename*(这是文件系统使用的真实文件名)。

加载文件foo与当前加载的文件调用相同的目录:

(load (merge-pathnames "foo" *load-pathname*))

要在与当前加载的文件调用相同的目录的子目录bar中加载文件foo :

(load (merge-pathnames "bar/foo" *load-pathname*))
于 2017-04-17T09:17:52.223 回答
0

使用 Common Lisp,我是这样完成的:

file1.lisp我定义一个函数sayHello并在包名下导出该函数helloLisp

(defpackage :helloLisp
    (:use :common-lisp)
    (:export #:sayHello))

(in-package :helloLisp)

(defun sayHello () (print "Hello!"))

在文件中file2.lisprequire这个文件是这样的:

(require "helloLisp" "./file1.lisp")

(helloLisp:sayHello)

使用 SBCL 1.4.11 测试

于 2020-11-11T12:29:05.267 回答