引用全局符号

时间:2018-10-13 23:12:54

标签: common-lisp

我想创建一个源文件,其中定义的大多数功能都位于该源文件的本地。通过标记函数static,这与在C中实现的目的相同。在C ++中,也可以用namespace { ... }包围它们。我对Lisp印象深刻,打包系统是合适的工具。但是,到目前为止,我的尝试均无效。

这是我目前拥有的,但是SBCL拒绝声明global-fun未定义。明确地将其称为cl-user:global-fun会产生相似的结果。我该怎么办?

(defun global-fun ()
  (format t "global~%"))

(defpackage :local-package
  (:use :common-lisp)
  (:use :cl-user))
(in-package :local-package)

(defun local-fun ()
  (global-fun)
  (format t "local~%"))

2 个答案:

答案 0 :(得分:4)

您快到了。您可以使用Slime的自动补全功能来找出答案。

要么导出global-fun,要么使用 double 冒号进行访问:(cl-user::global-fun)

与另一个global-package

(defpackage :global-package
 (:use :common-lisp) ;; <-- can be :cl
 ;; (:use :cl-user) <-- not necessary
 (:export :global-fun))

 (in-package :global-package)

(defun global-fun () …)

(defpackage :local-package
  (:use :cl
        :global-defun)) ;; <-- one ":use" is possible
(in-package :local-package)

; etc

答案 1 :(得分:2)

这里似乎存在一些误解。

Common Lisp中没有“全局函数”之类的东西。首先在文件中定义的内容global-fun some 包中,很可能是cl-user包。

软件包和文件之间也没有直接对应关系。您可以在一个文件中为不同的软件包定义内容,也可以在多个文件中为一个软件包定义内容。为使内容明确且易于阅读,有一个非常明智的约定,即始终以in-package格式(在某些样式中以defpackage格式开头)来启动源文件,而从不放置另一个{ {1}}在文件的后面。

编写不带包装的符号时,e。 G。 in-packagesomefun,它被嵌入(即某种幂等注册)到当前包中(请参见下文)。这与您当前定义或引用某些内容无关,因为它是在读取源代码形式时由 reader 完成的。在以下两种形式中,名为myarray的符号被插入到当前程序包中(并且两者都导致使用相同的符号):

foo

为了引用来自其他程序包的符号,您需要将程序包名称作为前缀,并以(defun foo () …) (foo) 作为分隔符,例如::,但这通常是代码味道,因为…

...您应该从包定义中导出包用户打算使用的所有符号:

my-package::foo

您可以使用另一个冒号,例如(defpackage my-package (:use common-lisp) (:export foo)) 引用另一个包中的 exported 符号,这是很好的样式。

现在,当前包仅仅是变量my-package:foo的值。如果从REPL会话的角度来看它,这是最近一次*package*调用的参数。在整个文件编译的上下文中,它是词法上最接近的in-package形式的值。在文件中进行单形式编译的情况下,IDE(无论如何见过)都将查找之前的in-package形式,即使未明确评估它也是如此。在原始的Lisp映像中,起始软件包为in-package,其昵称为common-lisp-user