在编写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的有益回答和后续行动。
接下来是有关该答案的一些注释,这些注释是从注释中整理出来的。
@Vsevolod,如果将它们添加到答案中,我将其删除。
提供的解决方案提供了更多功能;它还提供了一种从解释器而不是命令行运行代码的方法。
#!
定义reader macro function。如链接“在遇到宏字符时,Lisp阅读器将调用其阅读器宏功能”中所述。
阅读器功能由对
set-dispatch-macro-character
的调用定义。因此,当看到
#!
字符时,set-dispatch-macro-character
导致调用主体中定义的lambda函数。然后,此函数将关键字
:noscript
添加到 *features*
变量中。另请参见有关SO宏对读者宏有什么好处的讨论
Read macros: what do you use them for?。
:noscript
字符时,正是将关键字*features*
添加到#!
中。此外,#!
当代码在解释器中运行时出现字符,例如使用slime
时,但显然不存在(已删除)在程序的运行
sbcl --script
的文本。因此,当代码在interpeter中运行时,将:noscript
添加到*features*
中,但当以脚本。
#-/#+
,正如Vsevolod所说的,其行为类似于C的#IFDEF/#IFNDEF
。他们检查符号在
*features*
中。在这种情况下,#-:noscript
检查是否存在:noscript
,#+:noscript
检查是否存在:noscript
。如果满足这些条件,它将运行相应的代码。要包装一段代码,可以使用
progn
像这样:#-:noscript (progn <your code here>)
。 set-dispatch-macro-character
。在sbcl
的情况下,可以放在初始化文件
~/.sbclrc
中。请注意,此方法不取决于Common Lisp实现为SBCL。 :SWANK
时出现关键字*features*
。使用SLIME在emacs中使用REPL。 SWANK是SLIME的服务器端。 SLIME应该更准确地称为SLIME/SWANK,因为这两个是
客户端-服务器体系结构的客户端/服务器组件。我发现此博客文章Understanding SLIME很有帮助。
因此,除了不需要编写任何代码之外,可以像
#-:swank
和#+:swank
一样使用#-:noscript
和#+:noscript
。当然,如果使用命令行解释器
sbcl
,则此方法将无效,例如,从那时起,
:SWANK
将不会出现在*features*
中。 最佳答案
您可以使用以下技巧:
(set-dispatch-macro-character #\# #\!
(lambda (stream c n)
(declare (ignore c n))
(read-line stream)
`(eval-when (:compile-toplevel :load-toplevel :execute)
(pushnew :noscript *features*))))
#-:noscript
:#!/usr/local/bin/sbcl --script
(defun test (a) (print a))
(test 1)
#-:noscript (test 2)
#+:noscript (test 3)
执行
./test.lisp
将输出1和2,而C-c C-k将输出1和3。编辑
此技巧应该有效,因为通过SLIME或其他机制加载文件时,shebang行已被
sbcl --script
完全删除,但未被删除。这种方法的缺点是我们要以要素中不存在
:noscript
而不是:script
为条件。要对其进行修改,应在sbcl --script
处理本身中完成对适当功能的推送。
关于command-line - 编写从命令行执行但不在解释器内部执行的Common Lisp代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9796353/