我想创建一个源文件,其中定义的大多数功能都位于该源文件的本地。通过标记函数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~%"))
答案 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-package
或somefun
,它被嵌入(即某种幂等注册)到当前包中(请参见下文)。这与您当前定义或引用某些内容无关,因为它是在读取源代码形式时由 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
。