Command line 编写从命令行执行但不在解释器内部执行的公共Lisp代码
在编写公共Lisp代码时,我使用SLIME。特别是,我使用C-C-k编译包含函数定义的缓冲区,然后切换到REPL来运行这些函数。将运行这些函数的可执行代码放在缓冲区中似乎效果不太好。如果代码有bug,它可能会造成混乱 有一种方法可以很方便地包含不在缓冲区中编译但确实从命令行运行的代码,例如在执行以下操作时Command line 编写从命令行执行但不在解释器内部执行的公共Lisp代码,command-line,common-lisp,slime,sbcl,Command Line,Common Lisp,Slime,Sbcl,在编写公共Lisp代码时,我使用SLIME。特别是,我使用C-C-k编译包含函数定义的缓冲区,然后切换到REPL来运行这些函数。将运行这些函数的可执行代码放在缓冲区中似乎效果不太好。如果代码有bug,它可能会造成混乱 有一种方法可以很方便地包含不在缓冲区中编译但确实从命令行运行的代码,例如在执行以下操作时 sbcl --script foo.lisp 如果是这样的话,我就不必每次想从命令行运行代码时都不断地添加和删除代码。是否存在这种情况 这类似于Python条件 if __name__=='
sbcl --script foo.lisp
如果是这样的话,我就不必每次想从命令行运行代码时都不断地添加和删除代码。是否存在这种情况
这类似于Python条件
if __name__=='__main__':
如果Python文件作为模块导入,则为false;如果作为脚本运行,则为true
这篇名为“随机谷歌”的博客文章
;; 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,如果你把这些添加到你的答案中,我会删除它们
#定义一个代码>。
如链接中所述,“遇到宏字符时,Lisp读取器调用其读取器宏函数”。
读卡器函数由对的调用定义。
所以,当#代码>字符,则设置分派宏字符
会导致调用正文中定义的lambda函数。
然后,此函数将关键字:noscript
添加到变量中。
另请参见SO问题中有关reader宏的用途的讨论
:noscript
正是在\代码>字符存在。此外,#代码>
当代码在解释器内运行时,例如使用slime
时,字符出现,但程序的
sbcl的文本--script
正在运行。因此,当代码在interpeter中运行时,:noscript
被添加到*功能*
中,而不是作为
剧本
-/+
,正如Vsevolod所说,它的行为类似于to C的#IFDEF/#IFNDEF
。他们检查是否有符号在
*功能中*
。在这种情况下,-:noscript
检查是否存在:noscript
,以及+:noscript
检查是否存在:noscript
如果满足这些条件,它将运行相应的代码。要包装代码块,可以使用 像这样:
#-:noscript(progn)
set dispatch macro character
。在sbcl
的情况下,可以将
它位于初始化文件~/.sbclrc
中。请注意,这种方法不依赖于SBCL的公共Lisp实现使用粘液的emacs内部的REPL。SWANK是SLIME的服务器端。黏液应该更准确地称为黏液/SWANK,因为这两个是 客户机/服务器体系结构的客户机/服务器组件。我发现这篇名为的博文很有帮助 因此,人们可以使用
-:swank
和+:swank
就像-:noscript
和+:noscript
一样,只是不需要编写任何代码。
当然,例如,如果使用命令行解释器sbcl
,这将不起作用,
从那时起,:SWANK
将不会出现在*功能*
中您可以使用以下技巧:
(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-k将输出1和3sbcl--script
删除,但不会被删除
这种方法的缺点是,我们的条件是功能中不存在
:noscript
,而不存在:script
。要修改它,应该在sbcl--script
处理本身中推送适当的功能。Fare Rideau编写了一个漂亮的unix实用程序CL-Launch,它可以从命令行执行lisp软件。它集成了Quicklisp支持,可用于大多数常见的Lisp实现
示例脚本可能如下所示:
#!/usr/bin/cl -sp "hunchentoot" -Q -E main
(defun main (argv)
(format t "~A: ~{~A ~}~%" (truename ".") argv)
(hunchentoot:start
(make-instance 'hunchentoot:acceptor
:document-root (truename ".")
:port 8080))
(do ((x #\s (read-char)))
((char-equal x #\q) nil)))
在向脚本添加+x权限并调用它之后,它将在当前目录中启动http服务器。“-sp”标志表示要加载的包,因此它是从包中抽象shell脚本的一种相当干净的方法
有关更多详细信息,请参阅:
我有同样的问题,我刚刚偶然发现了这个讨论。至少在使用sbcl时,我似乎可以使用
(sbext:posix getenv“”)
。当在slime中运行时,它返回/usr/bin/emacs
(或指向emacs的任何路径),否则返回用于调用脚本的命令。因此,在您成为emacs参与者之前,始终可以区分slime和脚本调用:)
如果你想得到充分的赞扬