CLISP允许我们做
(compile nil #'(lambda(x) (+ x 1)))
这将返回一个已编译的函数对象:
#<COMPILED-FUNCTION NIL>
是否可以将其导出为二进制字符串,以便保留它?比如说,将其保存在数据库中,以后可以加载并运行已编译的函数。
答案 0 :(得分:5)
不在便携式Common Lisp中。
而是将函数写入文件,使用COMPILE-FILE
编译文件。然后,您在文件系统上有已编译的代码。您可以稍后加载该文件并运行该功能。您还可以将文件内容存储到数据库中。如果以后需要,则需要将数据库中的数据导出到文件中,并调用LOAD
加载文件。
答案 1 :(得分:4)
是的,在CLISP中你可以:
> (defparameter *my-function* (compile nil #'(lambda(x) (+ x 1))))
*MY-FUNCTION*
> *MY-FUNCTION*
#<COMPILED-FUNCTION NIL>
> (write-to-string *my-function* :readably t :pretty nil)
"#Y(|COMMON-LISP|::|NIL| #15Y(00 00 00 00 01 00 00 00 20 02 AD 32 B1 19 02) () (|COMMON-LISP|::|T| |COMMON-LISP|::|NIL| |COMMON-LISP|::|NIL|))"
> (defparameter *my-function-1* (read-from-string (write-to-string *my-function* :readably t)))
*MY-FUNCTION-1*
> (funcall *my-function-1* 10)
11
这可以在CLISP支持的所有平台上移植,并且只要CLISP字节码版本相同(每次发布时都不会更改)。
正如Rainer所说,其他CL实现不一定支持这一点,但你当然可以把你的函数放到一个文件中,编译文件,然后读入字符串:
(defun function-string (func)
(let ((lambda-expr (function-lambda-expression func)))
(unless lambda-expr
(error "no lambda expression for ~S" func))
(let ((tmp-file "tmp.lisp") comp-file ret)
(with-open-file (o tmp-file :direction :output)
(write (list* 'defun my-tmp-func (cdr lambda-expr))
:stream o :readably t))
(setq comp-file (compile-file tmp-file))
(with-open-file (compiled comp-file :direction :input
:element-type '(unsigned-byte 8))
(setq ret (make-array (file-length compiled)
:element-type '(unsigned-byte 8)))
(read-sequence ret compiled))
(delete-file tmp-file)
(delete-file comp-file)
ret)))
要恢复该功能,您需要使用load
:
(with-input-from-string (s (function-string *my-function*))
(load s))
(fdefinition 'my-tmp-func)
备注强>:
function-lambda-expression
的值可以合法地始终 nil
!