repl 和编译文件之间的 lisp 包差异

发布于 2024-09-15 16:12:41 字数 464 浏览 12 评论 0原文

我目前正在 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 包,但在编译文件时却找不到?

I'm currently playing with lispbuilder-sdl on SBCL under Windows.

My source code is as follows:

(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)

When I compile the file I get the error: package "SDL-EXAMPLES" not found.

If I remove the (sdl-examples:squashed) from the file it compiles ok. I can then type (sdl-examples:squashed) at the repl and the demo game starts fine.

Why is the sdl-examples package found from the repl but not when I compile the file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笙痞 2024-09-22 16:12:41

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

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

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

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


因此,这里有更多有关此处发生的情况的信息:

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

All of the compilation of that file happens before executing any of the load-ops. So when Lisp compiles the (sdl-examples:squashed) line, it hasn't run the load-op that defines your package.

You can get around this by not mentioning the sdl-examples package that requires the reader to locate its squashed symbol before the load-op is actually executed:

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

The idea is to calculate the package from its symbolic name, lookup the symbol naming your function, and fetch the function it names - but this way requires that the package exist only when the code is run, not when it is first read. Then your four statements can all be compiled, executed in order, and by the time that last statement is executed, your load-ops will have created the package.


So here's a little more info about what's happening here:

  • Writing '#:some-name refers to a symbol that's not part of any package. So that way we can make a reference to a symbolic name without either (1) assuming its package exists or (2) mucking up some other package with the name.
  • Then '(symbol-name #:some-name) extracts the name of the symbol as a string. Why not just write "some-name"? You could, and it will usually work. But this way is a little more robust for the case of running a "modern-mode" case-sensitive Lisp.
  • The find-package maps a string name to Lisp's representation of a package. Remember, by the time you run this line, your package will exist.
  • intern returns the symbol with the given name that lives in the given package.
  • symbol-function returns the function object (a lambda abstraction, or more likely, its compiled representation) associated with the symbol.
  • And then funcall invokes that function.
    It is kind of clunky, but unfortunately there's not really a better way to mix calls which load code to create a package with names living in that package in the same file.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文