Lisp 导出内部符号

Posted

技术标签:

【中文标题】Lisp 导出内部符号【英文标题】:Lisp exports internal symbols 【发布时间】:2020-01-07 06:24:36 【问题描述】:

我正在学习定义一个系统,并制作了一个名为 test 的小型测试包。它的结构如下所示:

test/
  test.asd
  hi.lip
  hito.lisp
  package.lisp

现在在 package.lisp 文件中我定义了我的包:

(in-package :cl-user)

(defpackage :test
  (:use #:cl)
  (:import-from #:uiop
        #:strcat)
  (:export #:sayhito))

在 test.asd 系统中:

(defsystem test
  :name "Testing"
  :components ((:file "package")
           (:file "hi")
           (:file "hito")))

在 hi.lisp 中,我有一个辅助函数 sayhi,它并不意味着是外部的:

(in-package :test)

(defun sayhi () "Hi")

以及hito.lisp中系统的外部函数hito

(in-package :test)

(defun sayhito (name)
  (strcat (sayhi) " " name "!"))

我还有一个目录 /home/amir/lisp-link-farm/ 我将所有 ASDF 的符号链接放入其中。然后在我的 lisp 初始化文件 (.sbclrc) 中,我将此路径推送到 asdf:*central-registry*:

;;; The following lines added by ql:add-to-init-file:
#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
                                   (user-homedir-pathname))))
  (when (probe-file quicklisp-init)
    (load quicklisp-init)))


;; where i am restoring symlinks to systems
(require 'asdf)
(push #p"/home/amir/lisp-link-farm/" asdf:*central-registry*)

现在,当我通过(ql:quickload :test) 加载测试系统并将包更改为(in-package :test) 时,内部辅助函数hi 也可以作为外部符号访问!我可以这样做:

(sayhi)   ;; -> "Hi"

但是如果我不更改包(所以在 REPL 中没有 (in-package :test))尝试调用 (test:sayhi) lisp 会抱怨 sayhi 不是包测试中的外部符号,而 (test:sayhito "Lisp") 可以正常工作应该。 为什么会发生这种情况,我做错了什么?任何帮助表示赞赏。

【问题讨论】:

相关:***.com/questions/47782593/… 【参考方案1】:

不,它不能作为外部符号访问。正如您自己编写的那样,您将包更改为有问题的包,这意味着它是您的当前包,并且所有符号解析在内部工作。就像在特定包中编写代码时一样:您可以引用包的所有符号而无需预先添加包。

请注意,即使您将当前包更改为 test,引用 test:hi(带有单个冒号)也会表示错误。

所以,你没有做错任何事,除了期望 REPL 有其他包解析规则而不是源文件。

【讨论】:

所以我系统的最终用户应该只是(ql:quickload :test) 没有(in-package :test) 然后使用限定名称来使用外部符号?否则他们可能会不小心覆盖我包裹的符号? 有两种情况:图书馆和交互系统。前者更为常见;在这里,您可以使用库有选择地从包中导入,如果有的话。如果您使用 REPL 作为交互式系统的用户界面,您通常会提供一个 test-user 包来导入 test 的公共符号。广泛使用的有cl-userasdf-user,例如。【参考方案2】:

看来你做得很好。如果导出函数,可以使用package:function (test:sayhito)(冒号)访问它。如果不导出,仍然可以使用双冒号访问:package::function (test::sayhi)。

当你一个包中时,你可以直接输入所有符号,不管是否导出,这就是目标。

【讨论】:

以上是关于Lisp 导出内部符号的主要内容,如果未能解决你的问题,请参考以下文章

如何找出从共享对象导出的所有符号?

导出符号意味着什么?

使用表情符号导出数据库

GCC默认导出所有符号与MSVC默认不导出任何东西之间的设计原理是啥?

内核符号导出

MySQL导入导出数据时遇到Tab符号和换行符号怎么办