views:

447

answers:

6

Is there any persistence solution for Common Lisp, such as Elephant, that allows function persistence? Currently my app stores an identifier on the db and later searches in a function table which it is, but this method does not allow dynamically created functions to be stored.

+1  A: 

Functions are opaque objects, so you won't have much luck storing them in files or something like that. You can, however, store lists and compile them upon retrieval from the database.

This won't help you store closures, of course. That would entail storing the lexical environment along with the code, neither of which you have (portable) access to. Code that you compile from stored lists will have to rely entirely on global data or data stored in the database.

By the way, note that you can funcall symbols, so you don't need a function table for global functions.

Matthias Benkard
+1  A: 

You can look into saving Lisp images. This allows saving "enough information to restart a Lisp process at a later time." You can have your functions saved after you have loaded them into your image.

This may also be a bit more advanced than what you were looking for, but here is a (very) brief introduction to the process: Saving a Core Image

contagious
+4  A: 

It's not a database persistence mechanism, but most Common Lisps have a way of writing FASLs for all kinds of objects, including functions. For example:

cl-user(1): (compile (defun hello () (format t "~&Hello~%")))
hello
nil
nil
cl-user(2): (excl:fasl-write (symbol-function 'hello) "/tmp/hello.fasl")
t
cl-user(3): (excl:fasl-read "/tmp/hello.fasl")
(#<Function hello @ #x1000a964d2>)

You can write to a stream (here I used a file for convenience), so you can trivially capture those bytes and stuff them into a database if you wished.

Rich
But you should note, that it isn't in the CL standard.
Anton Kazennikov
+2  A: 

Common Cold might be what you want. It includes serializable closures and serializable continuations.

Luís Oliveira
+2  A: 

Pascal Bourguignon gave a standard solution on comp.lang.lisp. Basically you have to write the source form to a file and COMPILE it then LOAD it.

(defvar *anon*)

(defun save-anonymous-function (fname args body)
  (let ((fname (make-pathname :type "LISP" :case :common :defaults fname)))
     (with-open-file (src fname :direction :output
                     :if-does-not-exist :create :if-exists :supersede)
       (print `(defparameter *anon* (lambda ,args ,body)) src))
     (compile-file fname)))

Then you’ll have to read the file and store it in your database. To get it back you’ll need to fetch it from the database and write it in a file before loading it.

(defun load-anonymous-function (fname)
   (let ((*load-verbose* nil)
         (*anon* nil)) ; to avoid modifying the global one.
     (load fname)
     *anon*))
kmkaplan
A: 

Be careful that storing code may not be that good. The Zope developers learned it the hard way.

J. Pablo Fernández
What is that supposed to mean? A little more explicitness would be much more useful...
Alex Ati