Fah*_*tha 10 command-line sbcl common-lisp slime
在编写Common Lisp代码时,我使用SLIME.特别是,我使用CC Ck编译包含函数定义的缓冲区,然后切换到REPL以运行这些函数.将可执行代码放在缓冲区中运行这些函数似乎不能很好地工作.如果代码有错误,它可能会弄得一团糟.
有一种方法可以包含不在缓冲区中编译的代码,但是可以从命令行运行,例如在执行时
sbcl --script foo.lisp
Run Code Online (Sandbox Code Playgroud)
如果是这种情况,每次我想从命令行运行代码时,我都不必继续添加和删除代码.是否存在这样的情况?
这类似于Python条件.
if __name__=='__main__':
Run Code Online (Sandbox Code Playgroud)
如果将Python文件作为模块导入,则为false;如果将其作为脚本运行,则为true.
这篇由Googling随机发现的题为"使用SBCL for Common Lisp shell脚本"的博文有
;; 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
)
Run Code Online (Sandbox Code Playgroud)
包含的代码确实不会被SLIME中的编译器运行,但它也不会被运行sbcl --script.
更新:感谢Vsevolod Dyomkin的有用答案和后续行动.关于该答案的一些注释如下,从对该答案的评论中汇编而成.@Vsevolod,如果你将这些添加到你的答案中,我会删除它们.
首先,我问了一种从命令行运行代码的方法,但不是从解释器运行代码.提供的解决方案做得更多; 它还提供了一种从解释器而不是命令行运行代码的方法.
第一步是为宏字符定义一个阅读器宏功能#!.如链接"在遇到宏字符时,Lisp读者调用其读取器宏函数"中所述.读者功能由调用来定义set-dispatch-macro-character.因此,当#!看到该字符时,set-dispatch-macro-character会导致调用正文中定义的lambda函数.然后,此函数将关键字添加:noscript到*features*变量中.另请参阅讨论哪些读取器宏在SO问题中
有用.阅读宏:您使用它们是什么?.
观察到关键字: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.
一个更简单的替代方案中,如在SBCL-devel的清单中提到,是使用关键字的事实:SWANK,当一个类型出现*features*在
使用泥一个REPL内部emacs的.SWANK是SLIME的服务器端.SLIME应该更准确地称为SLIME/SWANK,因为这两者是客户端 - 服务器体系结构的客户端/服务器组件.我发现这篇名为Understanding SLIME的博客文章很有帮助.
因此,除了不需要编写任何代码之外,可以使用#-:swank并且#+:swank只是喜欢#-:noscript和#+:noscript.当然,如果一个人正在使用命令行解释器sbcl,那么这:SWANK将不起作用,因为那时将不会出现*features*.
Vse*_*kin 13
您可以使用以下技巧:
为shebang定义一个调度函数:
(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*))))
Run Code Online (Sandbox Code Playgroud)在您的脚本文件中使用#-:noscript:
#!/usr/local/bin/sbcl --script
(defun test (a) (print a))
(test 1)
#-:noscript (test 2)
#+:noscript (test 3)
Run Code Online (Sandbox Code Playgroud)
执行./test.lisp将打印1和2,同时C-c C-k输出1和3.
EDITS
这个技巧应该有效,因为sbcl --script当通过SLIME或其他机制加载文件时,shebang行被完全删除但不被删除.
这种方法的缺点是我们的条件是没有:noscript特征,而不是存在:script.要修改它,应该在sbcl --script处理过程中推送适当的功能.
Fare Rideau 编写了一个漂亮的 unix 实用程序 CL-Launch,它可以从命令行执行 lisp 软件。它集成了 Quicklisp 支持并适用于大多数 Common 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)))
Run Code Online (Sandbox Code Playgroud)
给脚本添加+x 权限并调用它后,它将在当前目录中启动http 服务器。“-sp”标志表示您要加载的包,因此它是从包中提取 shell 脚本的相当干净的方式。
更多详情请参考:http : //cliki.net/CL-Launch