repl和compile文件之间的lisp包差异

时间:2010-08-24 19:13:58

标签: lisp package read-eval-print-loop

我目前正在Windows下的SBCL上玩lispbuilder-sdl。

我的源代码如下:

(asdf:operate 'asdf:load-op :lispbuilder-sdl)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-binaries)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-examples)
(sdl-examples:squashed)

当我编译文件时,我收到错误:找不到包“SDL-EXAMPLES”。

如果我从文件中删除(sdl-examples:squashed)它编译好了。然后我可以在repl上键入(sdl-examples:squashed)并且演示游戏开始正常。

为什么从repl中找到sdl-examples包,但在编译文件时却找不到?

1 个答案:

答案 0 :(得分:2)

该文件的所有编译都在执行任何load-op之前发生。因此,当Lisp编译(sdl-examples:squashed)行时,它没有运行定义包的load-op

您可以通过不提及要求读者在sdl-examples实际执行之前找到其squashed符号的load-op包来解决这个问题:

(funcall (symbol-function (intern (symbol-name '#:squashed)
                                  (find-package (symbol-name '#:sdl-examples)))))

这个想法是从它的符号名称计算包,查找命名你的函数的符号,并获取它命名的函数 - 但是这种方式要求包只在代码运行时存在,而不是在第一次读取时存在。然后你的四个语句都可以被编译,按顺序执行,并且在执行最后一个语句的时候,你的load-op将创建包。


所以这里有关于这里发生了什么的更多信息:

  • '#:some-name指的是不属于任何包的符号。因此,我们可以在没有(1)假设其包存在的情况下或(2)使用名称包含其他包的情况下引用符号名称。
  • 然后'(symbol-name #:some-name)将符号的名称提取为字符串。为什么不写"some-name"?你可以,它通常会起作用。但对于运行“现代模式”区分大小写的Lisp来说,这种方式更为强大。
  • find-package将字符串名称映射到Lisp的包表示。请记住,当您运行此行时,您的包将存在。
  • intern返回具有给定包名的给定名称的符号。
  • symbol-function返回与符号关联的函数对象(lambda抽象,或更可能是其编译表示)。
  • 然后funcall调用该函数。 它有点笨重,但不幸的是,实际上并没有更好的方法来混合调用,这些调用加载代码来创建一个包含在同一文件中的包中的名称。