Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

serialization of functions/closures

226 views
Skip to first unread message

Tamas K Papp

unread,
Jan 1, 2009, 10:44:10 AM1/1/09
to
Hi,

I am looking for a serialization library that would also serialize
closures/functions. Is this possible at all? The cliki page for cl-
store says "Hopefully one day proper functions and closures will be
added." How can one do that?

Thanks,

Tamas

Stanisław Halik

unread,
Jan 1, 2009, 11:49:39 AM1/1/09
to
thus spoke Tamas K Papp <tkp...@gmail.com>:

> Hi,
> I am looking for a serialization library that would also serialize
> closures/functions.

SB-HEAPDUMP.

--
You only have power over people so long as you don’t take everything
away from them. But when you’ve robbed a man of everything he’s no longer
in your power — he’s free again. -- Aleksandr Isayevich Solzhenitsyn

Volkan YAZICI

unread,
Jan 1, 2009, 2:58:32 PM1/1/09
to

You can search c.l.l archives using "serialize" and "closure" keywords
for various discussions about the subject.


Regards.

Pascal Costanza

unread,
Jan 1, 2009, 3:20:50 PM1/1/09
to

Closures are hard: When serialized to another location, do you want to
see the same bindings as the original closure? Do you want to ensure
that side effects on the bindings are signaled back to the original
location? Should side effects from the original location always be
propagated to the new location?

Functions that don't close over anything are easy. Here is a sketch that
we used in some project:

(in-package :closer-common-lisp-user)

(defgeneric update-instance-after-reading (object)
(:method ((object t)) object))

(defclass value-object () ())

(defun value-object (class-name &rest initargs)
(declare (dynamic-extent initargs))
(let ((object (allocate-instance (find-class class-name))))
(loop for (slot-name value) on initargs by #'cddr do
(setf (slot-value object slot-name) value))
(update-instance-after-reading object)))

(defun print-value-object (object stream)
(let ((*print-circle* nil))
(format stream "#.(VALUE-OBJECT '~S" (class-name (class-of object)))
(loop for slot in (class-slots (class-of object))
unless (eq (slot-definition-allocation slot) :class) do
(format stream " '~S '~S"
(slot-definition-name slot)
(slot-value object (slot-definition-name slot))))
(format stream ")")))

(defmethod print-object ((object value-object) stream)
(if *print-readably*
(print-value-object object stream)
(call-next-method)))

(defclass funcallable-value-object ()
((definition :initarg :definition
:reader funcallable-instance-definition))
(:metaclass funcallable-standard-class))

(defmethod initialize-instance :after
((object funcallable-value-object) &key definition)
(set-funcallable-instance-function object (compile nil definition)))

(defmethod reinitialize-instance :after
((object funcallable-value-object) &key (definition nil definitionp))
(when definitionp
(set-funcallable-instance-function
object (compile nil definition))))

(defmethod update-instance-after-reading :after
((object funcallable-value-object))
(set-funcallable-instance-function
object (compile nil (funcallable-instance-definition object))))

(defmethod print-object ((object funcallable-value-object) stream)
(if *print-readably*
(print-value-object object stream)
(call-next-method)))

(defmacro vlambda ((&rest lambda-list) &body body)
`(make-instance 'funcallable-value-object
:definition '(lambda ,lambda-list ,@body)))

(defmacro define-vfunction (name (&rest lambda-list) &body body)
`(progn
(declaim (notinline ,name))
(defun ,name ,lambda-list)
(setf (fdefinition ',name)
(vlambda ,lambda-list ,@body))
',name))


--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/

Volkan YAZICI

unread,
Jan 2, 2009, 2:33:38 AM1/2/09
to

Despite dozens of previous closure serialization related threads, this
is the first time I see such a CLOS hack for wrapping classes around
(almost pseudo) functions for serialization purposes. Neat! Which
resource (article, book, etc.) one should _digest_ to be able to do
similar CLOS hacks?


Regards.

Pascal Costanza

unread,
Jan 2, 2009, 5:48:10 AM1/2/09
to
Volkan YAZICI wrote:
> On Jan 1, 10:20 pm, Pascal Costanza <p...@p-cos.net> wrote:
>> Closures are hard: When serialized to another location, do you want to
>> see the same bindings as the original closure? Do you want to ensure
>> that side effects on the bindings are signaled back to the original
>> location? Should side effects from the original location always be
>> propagated to the new location?
>>
>> Functions that don't close over anything are easy. Here is a sketch that
>> we used in some project:
[...]

> Despite dozens of previous closure serialization related threads, this
> is the first time I see such a CLOS hack for wrapping classes around
> (almost pseudo) functions for serialization purposes. Neat! Which
> resource (article, book, etc.) one should _digest_ to be able to do
> similar CLOS hacks?

There is no single article or book that helps to come up with such a
solution.

The ingredients are the following:

+ Ignore people who say that CLOS sucks. ;) They just don't understand
it and don't know what they are talking about. [1]

+ Especially understand that CLOS is not about OOP, but about generic
functions. That's an important shift of perspective. If you cannot make
that shift, you don't "get" it. Read Jim Newton's and Christophe Rhode's
papers about custom specializers for CLOS, or my paper about Filtered
Dispatch - these papers should help getting that perspective.

+ Read about the CLOS MOP. The important material is: Andreas Paepcke,
"User-Level Language Crafting"; Gregor Kiczales et al., "The Art of the
Metaobject Protocol"; http://www.lisp.org/mop/

+ Read about macros. I learned macros from Paul Graham's "On Lisp", but
Peter Norvig's "Paradigms of Artificial Intelligence Programming" is
also good reading.

+ Read about metacircular interpreters. I can especially recommend
Steele's and Sussman's "The Art of the Interpreter" (see the Lambda
Papers at http://library.readscheme.org ). Paul Graham's "The Roots of
Lisp" may also be helpful as a starting point. Other people recommend
SICP and PAIP, but I don't find them that illuminating in this regard.

+ Finally the hard point: Try to understand reflection and especially
3-Lisp. There is a section about reflection at
http://library.readscheme.org but the original material about 3-Lisp is
harder to find. I can recommend Charlotte Herzeel's paper "Reflection
for the Masses" as introductory reading. (If you can find the "Interim
3-Lisp Manual", that's also highly recommended.)

What's important in the context of the code posted here is that there is
a notion of "shifting up" and "shifting down" in 3-Lisp when you switch
between meta-level and base-level code. (compile nil '(lambda ...)) is a
way in Common Lisp to "shift down" from a description of some code to an
actual function that runs this code. In Common Lisp, however, there is
no corresponding operation to "shift up" from a function back to its
description - what the value functions do in this code is basically
provide a way to "shift up" by recording the function definition that
produced the function and keeping it available.

CLOS already needs such a way to "shift up" and "shift down" - whenever
you add a method to a generic function, a new ("discriminating")
function is computed (by way of a "downshift"), but the list of methods
associated with a generic function needs to be maintained for
introspection. So the solution here is to basically just reuse this
machinery, which is exposed in the CLOS MOP by way of funcallable objects.

+ Another important point is to make the serialization itself work. I
can highly recommend Arthur Lemmens's "Persistence in Common Lisp" in
this regard, which discusses how to use #. for serialization, including
its disadvantages (which can be serious, depending on the actual
requirements!).


I hope this helps.


Pascal


[1] This applies even to people who have been using CLOS for years, and
then came to the "conclusion" that CLOS sucks. (That's the disadvantage
of trying hard to remain a mere application programmer, you don't think
hard enough about what you're doing.)

Rob Warnock

unread,
Jan 2, 2009, 6:11:26 AM1/2/09
to
Pascal Costanza <p...@p-cos.net> wrote:
+---------------

| Volkan YAZICI wrote:
| > Which resource (article, book, etc.) one should _digest_ to
| > be able to do similar CLOS hacks?
...

| + Read about metacircular interpreters. I can especially recommend
| Steele's and Sussman's "The Art of the Interpreter" (see the Lambda
| Papers at http://library.readscheme.org ). Paul Graham's "The Roots of
| Lisp" may also be helpful as a starting point. Other people recommend
| SICP and PAIP, but I don't find them that illuminating in this regard.
+---------------

Better, at least for the serious student, is Christian Queinnec's
"Lisp in Small Pieces" (LiSP) [Les Langages Lisp, in the original
French]. What's really good about this one is that for each language
feature that it covers, it gives you several approaches to implementing
it and discusses the tradeoffs. I perticularly liked Chapter 6, "Fast
Interpretation", which discusses preprocessing [in CL terms, think
"minimal compilation"] to speed interpretation.


-Rob

-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607


Alex Mizrahi

unread,
Jan 2, 2009, 10:27:18 AM1/2/09
to
VY> is the first time I see such a CLOS hack

i'd say it is nearly trivial use of funcallable instances.

VY> Which resource (article, book, etc.) one should
VY> _digest_ to be able to do similar CLOS hacks?

i guess MOP documentation should do.


Matthew D Swank

unread,
Jan 3, 2009, 4:22:06 AM1/3/09
to
On Fri, 02 Jan 2009 11:48:10 +0100, Pascal Costanza wrote:

> + Ignore people who say that CLOS sucks. They just don't understand it


> and don't know what they are talking about. [1]

...

>
> [1] This applies even to people who have been using CLOS for years, and
> then came to the "conclusion" that CLOS sucks. (That's the disadvantage
> of trying hard to remain a mere application programmer, you don't think
> hard enough about what you're doing.)

Kenny ends up in threads in which he's not even participating.

--
Expect the worst, it's the least you can do.

0 new messages