freenode/#lisp - IRC Chatlog
Search
7:18:58
drmeister
Clasp writes out code and data for each top level form and then plays them back at load time. I’m looking for something better that doesn’t require support from the gc
7:21:12
drmeister
I think of it like a painting. Clasp saves every brush stroke even the ones that are covered up by later stokes. Then it replays them when it loads.
7:21:45
Zhivago
Particularly where that machine has read from a file or opened a socket or whatever.
7:22:09
drmeister
I can’t save the image of a running machine because I don’t have the support of the gc.
7:22:18
Zhivago
Are you limiting it to the case of a machine which has just loaded stuff before running stuff?
7:23:26
drmeister
I’m not sure what the trade offs are. I would imagine starting up a single thread and opening files at startup.
7:28:04
drmeister
I’ve been thinking that I have a symbol table and a bunch of code and classes, load time values etc. if I inventory them and write code to save and restore them - would that do the job
7:28:49
Zhivago
Sounds reasonable. If you evaluate the symbols in those forms before saving you may avoid circularity issues.
7:31:20
Zhivago
We would expect true (EQL *a* *b*), but if *b* were restored by generating code which produced a value equivalent to that of *a*, then (EQL *a* *b*) would become false.
7:33:08
Zhivago
And then could add (setf *a* *b*) after that to show that if you fix that problem you re-introduce the order of effects issue.
7:33:53
Zhivago
But you could be a little more clever and have the sharing of sub-structure preserved by the regeneration code.
7:34:44
drmeister
What about having the gc compact all live objects, write them out, and then reload and relocate them.
7:35:42
drmeister
I’d like to do that but I have to get hold of the raven brook folks to get some library support
7:37:22
Zhivago
The only case I can think of would be where you have running threads or values hidden in closures.
7:38:09
Zhivago
I'd think of the requirement that there be no running threads at the point of save-image.
7:39:36
drmeister
Clasp has special issues. It represents objects using 450 c++ classes. They have all sorts of data hidden in them.
7:42:15
Zhivago
There's no portable way to find that 3 given *a*, but since you're part of the implementation you don't need a portable way to do it.
7:42:52
Zhivago
I'm gradually coming to the conclusion that closures of indefinite extent are a bad idea.
9:09:25
dmiles
its: is_eq(X,Y):- X==Y , (\+ compound(X)-> true ; \+ \+ ((gensym(cookie,Cook),setarg(1,X,Cook),X==Y))).
9:12:12
Zhivago
So if you're making EQ more expensive than EQL, just have them share the same implementation.
9:13:13
Zhivago
You might consider something like is_eq(X, Y) :- object_identity(X) == object_identity(Y).
9:15:12
dmiles
of for 'objects' i use (objpointer 1111111111) == (objpointer 2222222) but for conses it walks over them
9:18:45
dmiles
symbols are interned objects so they end up with the same pointers (so good for me so far)
9:24:13
dmiles
(LIST (SETF my-point (make-point :x 3 :y 4 :z 12 ))(SETF my-point2 (make-point :x 3 :y 4 :z 12 ))) ==> (#<claz_u_point 10> #<claz_u_point 11> )
9:25:07
dmiles
*nod* .. in that case they are pointered.. i was hoping to not globally allocate simple vecotrs
9:30:28
dmiles
in a way i sorta got for free that beloved identity ;/ (that not sure i really wanted :P)
9:36:52
dmiles
horrible slow code " is_eq(X,Y):- X==Y , (\+ compound(X)-> true ; \+ \+ ((gensym(cookie,Cook),setarg(1,X,Cook),X==Y)))." compare datastrcuure value.. if they are the same poke a hole in one and see if they are still the same
9:42:25
loke
dmiles: It does, in the sense that a compliant CL implementation can return either NIL or T for that form.
9:47:10
loke
dmiles: No. EQ should return NIL if the objects are different. MAKE-WHATEVER creates a _new_ instance, so those two instances are distinctly different.
9:54:40
loke
dmiles: No. It's guaranteed to return NIL... The relevant quote from the Hyperspec: “subseq always allocates a new sequence for a result; it never shares storage with an old sequence.”
9:59:35
dmiles
ok soo... (eq #c(3 -4) #c(3 -4)) (eq #(3 -4) #(3 -4)) are undefined.. are their any others you can think of off hand?
10:02:30
pjb
dmiles: the reason why (eq "Foo" "Foo") and(eq #(3 -4) #(3 -4)) are undefined, is because "Foo" and #(3 -4) are literal objects, and when file-compiling, they may be coalesced to the same object (and put in read-only memory).
10:03:23
pjb
(eq (make-string 3 :initial-element #\F) (make-string 3 :initial-element #\F)) --> NIL is defined.
10:04:52
pjb
(eq '#.(make-string 3 :initial-element #\F) '#.(make-string 3 :initial-element #\F)) is not defined, because both strings "FFF" created at read-time (they're not EQ, there are two of them), but they are both compiled as literal objects because of the quote, and file-compile can coalese them to a single and same string "FFF".
10:05:11
pjb
basically: before file-compile it would return NIL, after file-compile it can return T.
10:07:31
pjb
dmiles: in a first version, you could take all the shortcuts allowed by CL… (defun eq (x y) (eql x y)) (defun delete (…) (remove …)) ; etc.
10:13:29
dmiles
ha lordy i just found http://www.swi-prolog.org/pldoc/doc_for?object=same_term/2 slightly cheaper than " is_eq(X,Y):- X==Y , (\+ compound(X)-> true ; \+ \+ ((gensym(cookie,Cook),setarg(1,X,Cook),X==Y)))." but i swear that was there a year ago