Хранение скомпилированной функции Lisp в базе данных
CLISP позволяет нам делать
(compile nil #'(lambda(x) (+ x 1)))
Это возвращает объект скомпилированной функции:
#<COMPILED-FUNCTION NIL>
Можно ли экспортировать это как двоичную строку, чтобы сохранить это? Скажем, сохраняя его в базе данных, а затем сможете загружать и запускать скомпилированную функцию.
2 ответа
CLISP
Да, в 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 одинакова (она не меняется при каждом выпуске).
Другие реализации
Как сказал Райнер, другие реализации 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
в данной реализации!- Если реализация компилируется в собственный код, приведенная выше строка будет зависеть от платформы.
- Я замял вопрос о пакетах...
Не в портативном Common Lisp.
Вместо этого запишите функцию в файл, скомпилируйте файл с COMPILE-FILE
, Тогда у вас есть скомпилированный код в файловой системе. Вы можете позже загрузить файл и запустить функцию. Вы также можете сохранить содержимое файла в базе данных. Если вам это понадобится позже, вам нужно будет экспортировать данные из базы данных в файл и вызвать LOAD
загрузить файл.