有没有办法实现compile-file
的效果,但不能使用磁盘上的常规文件,但是使用流或只是内存中的字符串? (即,如果我没有文件,并且不想使用此内存数据创建临时文件)
修改
我正在考虑以下用例:从文件系统以外的其他地方加载代码。例如,来自档案(类似于Java的jar或Python zip处理功能)或来自网络。也许可能有其他方法,而不仅仅是弯曲compile-file
机器。
答案 0 :(得分:3)
Rainer Joswig的第一条评论指出:
不在标准Common Lisp中。
您可以在每个实现中搜索从compile-file
进行的调用,以查看底层实现是否需要流。
如果您想自己实现这一目标,那么您将为输入和输出流实现一个非常低效的compile-file
版本,以生成适用于load
或您自己的版本的可加载表单。
使用with-compilation-unit
包装编辑,您必须特别注意macroexpand
顶级表单,确保将progn
表单视为顶级表单, locally
,macrolet
和symbol-macrolet
形式建立绑定并将其表单作为顶层处理,具有非空词汇环境(其操作也不可移植),并且处理{ {1}}表单,其中某些表单可以被评估,处理或两者兼而有之。然后,生成可外化的表单,关注可以合并的内容和不能合并的内容(例如符号和包),为eval-when
,make-load-form
和standard-object
实例调用structure-object
,以及特别注意符号和包,例如检查要编译的流是否具有第一个非原子condition
形式,以便能够在使用不同值调用in-package
时发出错误信号load
。
这只是最小化编译的最重要步骤,或多或少,不提及编译何时实际发生(编译时或加载时),*package*
形式和许多细节。有些步骤需要代码行走。
我的建议:只需从压缩数据和套接字中提取并保存任何源代码,然后调用load-time-value
后跟compile-file
,如果要保留编译和加载语义。对于更简单的事情,您可以这样做:
load
如果您不太关心可移植性,请使您的实现能够处理压缩文件,例如,向(let* ((*package* *package*)
(*readtable* *readtable*)
(eof (copy-symbol 'eof))
(form nil))
(loop
(setf form (read stream nil eof))
(when (eq form eof)
(return))
(funcall (compile nil `(lambda () ,form)))))
提供解压缩外部格式,并使您的实现能够打开URL(URI的,IRI,无论你关心什么)而不仅仅是路径名。 AFAIK,ABCL可以打开URL进行输入。然而,当用这样的外部资源调用时,compile-file
的输出文件是什么?也许制作自己的compile-file
,其中说明临时文件用于compile-and-load
的{{1}}关键参数和compile-file
。