在另一个lisp文件中调用函数

时间:2013-11-01 17:01:18

标签: emacs load lisp common-lisp

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

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

E.g。 file1.lisp有一个名为function1的函数,file2.lisp有一个名为function2的函数。 如何从function1调用function2?

谢谢!

4 个答案:

答案 0 :(得分:5)

您知道,有各种不同的Lisp系统。我将发布Common Lisp的答案。

天真的方式是使用(load "filename.lisp"),但这在一段时间后效果不佳。因此...

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

  1. 创建ASDF查找文件的目录。
  2. 将此信息添加到我的Lisp系统的init文件中。
  3. 我在.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中(来自defsystem中组件cl-linq.lisp的{​​{1}}),然后将"cl-linq"文件符号链接到我的cl-linq.asd目录。

    在我的cl-linq.lisp文件中,我包括:

    ~/.asdf/

    所以对于你的情况,我会有2个组件;每个都有自己的defpackage形式,导出功能,而另一个包需要。

    对于这些例子,我采用了CL-LINQ的代码,这是我的一个项目。您可以将其用作模板。

答案 1 :(得分: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或键盘快捷方式调用该函数。

答案 2 :(得分:0)

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

加载文件:fasl或来源

而不是(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*))

答案 3 :(得分:0)

我用Common Lisp做到了:

file1.lisp中,我定义了一个函数sayHello,并以包名helloLisp导出了该函数

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

(in-package :helloLisp)

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

在文件file2.lisp中,我require就是这样的文件:

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

(helloLisp:sayHello)

经过SBCL 1.4.11测试