【发布时间】:2012-03-20 23:03:53
【问题描述】:
在编写 Common Lisp 代码时,我使用 SLIME。特别是,我使用 C-C C-k 编译包含函数定义的缓冲区,然后切换到 REPL 来运行这些函数。将可执行代码以在缓冲区中运行这些函数似乎效果不佳。如果代码有错误,可能会造成混乱。
如果有一种方法可以方便地包含不会在缓冲区中编译但可以从命令行运行的代码,例如做的时候
sbcl --script foo.lisp
如果是这样,我就不必在每次想从命令行运行代码时都不断添加和删除代码。有这样的条件吗?
这类似于 Python 条件。
if __name__=='__main__':
如果将 Python 文件作为模块导入,则为 false,但如果作为脚本运行,则为 true。
这篇题为"Using SBCL for Common Lisp shell scripting"的博文,随机谷歌搜索,有
;; If run from command line, the following if-test will succeed
(if (> (length sb-ext:*posix-argv*) 1)
;; Code that is executed from the command line only goes here
)
包含的代码确实不会被 SLIME 中的编译器运行,但它也不会被 sbcl --script 运行。
更新:感谢 Vsevolod Dyomkin 的有用回答和跟进。 以下是关于该答案的一些注释,由 cmets 编译为该答案。 @Vsevolod,如果您将这些添加到您的答案中,我会删除它们。
首先,我要求一种从命令行而不是解释器运行代码的方法。 提供的解决方案做得更多;它还提供了一种从解释器而不是命令行运行代码的方法。
第一步是为宏字符
#!定义一个reader macro function。 如链接“在遇到宏字符时,Lisp 阅读器调用其阅读器宏函数”中所述。 阅读器函数由对set-dispatch-macro-character的调用定义。 因此,当看到#!字符时,set-dispatch-macro-character会导致调用正文中定义的 lambda 函数。 然后,此函数将关键字:noscript添加到*features*变量中。 另请参阅 SO question 中有关阅读器宏的用途的讨论 Read macros: what do you use them for?。观察到关键字
:noscript恰好在#!字符出现时添加到*features*。此外,#!当代码在解释器中运行时出现字符,例如使用slime时,但显然不存在(已从程序中删除)
运行sbcl --script的文本。因此,:noscript被添加到*features*中,当代码在 interpeter 中运行时,而不是作为 a
脚本。我们现在使用内置阅读器宏
#-/#+,正如 Vsevolod 所说,其行为类似于 C 的#IFDEF/#IFNDEF。他们检查符号
在*features*。在这种情况下,#-:noscript会检查:noscript是否存在,#+:noscript会检查:noscript是否存在。
如果满足这些条件,它将运行相应的代码。要包装一段代码,可以使用progn像这样:#-:noscript (progn <your code here>)。最后,在运行使用此功能的代码之前,需要调用
set-dispatch-macro-character。在sbcl的情况下,可以放 它在初始化文件~/.sbclrc中。请注意,这种方法不依赖于 SBCL 的 Common Lisp 实现。-
如 sbcl-devel 列表中所述,一个更简单的替代方法是使用关键字
:SWANK在输入*features*时出现
在 emacs 中使用 SLIME 的 REPL。 SWANK 是 SLIME 的服务器端。 SLIME 应该更准确地称为 SLIME/SWANK,因为这两个是 客户端-服务器架构的客户端/服务器组件。我发现这篇名为 Understanding SLIME 的博文很有帮助。因此,可以像使用
#-:noscript和#+:noscript一样使用#-:swank和#+:swank,只是不需要编写任何代码。 当然,如果使用命令行解释器sbcl,这将不起作用,例如, 此后:SWANK将不会出现在*features*中。
【问题讨论】:
标签: command-line common-lisp slime sbcl