From: John Thingstad on
I am writing a 'guess the animal' game for my Lisp book of games.
This game uses a binary deduction tree.
The thing is this tree needs to be stored to and loaded from disk. This
is a simple game and I don't want it to depend on external libraries like
object-store. I figure the best way to do this is to store the CLOS tree
as the code I would write to contruct the tree. That way I can just use
read to recontruct it. Never the less the code here looks a bit uggy at
least in (defmethod store ((item tree-node))).
Do you see a better way to do this?


(defmacro awhen (predicate &body body)
`(let ((it ,predicate))
(when it
,@body)))

;;; Commentary
;;;
;;; The data structure used is a binary deduction tree.
;;; From the tunk on down are questions.
;;; At the leaf nodes are animals.
;;; The deduction treee needs to set up a toxonometry so that
;;; it from a yes or no answers can deduce a unique animal.
;;; If it is not find it after traversing to the leafes
;;; it askes the user to same questions again.
;;; This makes the cursor travers to a leaf node of the tree.
;;; If there is already a animal there it askes for a
;;; question that will distinguish them.

(defclass item ()
())

(defclass question (item)
((question :accessor text :initarg :text)))

(defclass animal (item)
((animal :accessor species :initarg :species)))

(defclass tree ()
((root :accessor root :initarg :root :initform nil)
(cursor :accessor cursor :initform nil)))

(defclass tree-node (item)
((item :accessor item :initarg :item)
(left-child :accessor left-child :initarg :left-child :initform nil)
(right-child :accessor right-child :initarg :right-child :initform
nil)))

(defmethod initialize-instance :after ((item tree) &key &allow-other-keys)
(setf (slot-value item 'cursor) (slot-value item 'root)))

(defgeneric store (class stream))

(defmethod store ((item question) stream)
(print `(make-instance 'question :text ,(text item)) stream))

(defmethod store ((item animal) stream)
(print `(make-instance 'animal :species ,(species item)) stream))

(defmethod store ((item tree-node) stream)
(write-string "(make-instance 'tree-node " stream)
(write-string ":item " stream)
(store (item item) stream) (values)
(awhen (left-child item)
(write-string ":left-child " stream)
(store it stream))
(awhen (right-child item)
(write-string ":right-child " stream)
(store it stream))
(write-string ")" stream)
(values))
From: Pillsy on
On Nov 6, 11:08 am, John Thingstad <jpth...(a)online.no> wrote:
> I am  writing a 'guess the animal' game for my Lisp book of games.
> This game uses a binary deduction tree.
> The thing is this tree needs to be stored to and loaded from disk. This
> is a simple game and I don't want it to depend on external libraries like
> object-store. I figure the best way to do this is to store the CLOS tree
> as the code I would write to contruct the tree. That way I can just use
> read to recontruct it.

It might be easier to make the tree out of conses or STRUCTURE-CLASS
instances, both of which can be printed readably?

STRUCTURE-CLASSes even support (single) inheritance and generic
function methods can specialize on them, in case you want to retain
that functionality.

Cheers,
Pillsy
From: John Thingstad on
Den Fri, 06 Nov 2009 08:45:50 -0800, skrev Pillsy:

> On Nov 6, 11:08 am, John Thingstad <jpth...(a)online.no> wrote:
>> I am  writing a 'guess the animal' game for my Lisp book of games. This
>> game uses a binary deduction tree. The thing is this tree needs to be
>> stored to and loaded from disk. This is a simple game and I don't want
>> it to depend on external libraries like object-store. I figure the best
>> way to do this is to store the CLOS tree as the code I would write to
>> contruct the tree. That way I can just use read to recontruct it.
>
> It might be easier to make the tree out of conses or STRUCTURE-CLASS
> instances, both of which can be printed readably?
>
> STRUCTURE-CLASSes even support (single) inheritance and generic function
> methods can specialize on them, in case you want to retain that
> functionality.
>
> Cheers,
> Pillsy

I have not made myself clear. In each of my games I try to use different
tecniques and different approaches. I want to use classes it is just the
way it stores itself I don't like. In particular I don't like write-
string and would have prefered princ.

Basically just one huge line. To pprint it would look nice but would
require the entire structure to be held in RAM and that is just to
wastfull. (Call me old fashioned, but I hate waste.)

From: Pascal J. Bourguignon on
John Thingstad <jpthing(a)online.no> writes:

> Den Fri, 06 Nov 2009 08:45:50 -0800, skrev Pillsy:
>
>> On Nov 6, 11:08�am, John Thingstad <jpth...(a)online.no> wrote:
>>> I am �writing a 'guess the animal' game for my Lisp book of games. This
>>> game uses a binary deduction tree. The thing is this tree needs to be
>>> stored to and loaded from disk. This is a simple game and I don't want
>>> it to depend on external libraries like object-store. I figure the best
>>> way to do this is to store the CLOS tree as the code I would write to
>>> contruct the tree. That way I can just use read to recontruct it.
>>
>> It might be easier to make the tree out of conses or STRUCTURE-CLASS
>> instances, both of which can be printed readably?
>>
>> STRUCTURE-CLASSes even support (single) inheritance and generic function
>> methods can specialize on them, in case you want to retain that
>> functionality.
>>
>> Cheers,
>> Pillsy
>
> I have not made myself clear. In each of my games I try to use different
> tecniques and different approaches. I want to use classes it is just the
> way it stores itself I don't like. In particular I don't like write-
> string and would have prefered princ.
>
> Basically just one huge line. To pprint it would look nice but would
> require the entire structure to be held in RAM and that is just to
> wastfull. (Call me old fashioned, but I hate waste.)

I would avoid using write-string to print something that will be read
back. Build a sexp, and print it. (Avoid pprint for serialization
since it's slower).

If you have really a lot of data, you could just write one "(" at the
start, and one ")" at the end, and in the middle print several sexps
in a loop (they'll be garbage collected once printed if it is meed).

Of course, this works better if you can linearize the data structure.
Happily, it is easy to put a tree in prefix or suffix form.

--
__Pascal Bourguignon__
From: Barry Margolin on
In article <87fx8rcqbq.fsf(a)galatea.local>,
pjb(a)informatimago.com (Pascal J. Bourguignon) wrote:

> John Thingstad <jpthing(a)online.no> writes:
>
> > Den Fri, 06 Nov 2009 08:45:50 -0800, skrev Pillsy:
> >
> >> On Nov 6, 11:08�am, John Thingstad <jpth...(a)online.no> wrote:
> >>> I am �writing a 'guess the animal' game for my Lisp book of games. This
> >>> game uses a binary deduction tree. The thing is this tree needs to be
> >>> stored to and loaded from disk. This is a simple game and I don't want
> >>> it to depend on external libraries like object-store. I figure the best
> >>> way to do this is to store the CLOS tree as the code I would write to
> >>> contruct the tree. That way I can just use read to recontruct it.
> >>
> >> It might be easier to make the tree out of conses or STRUCTURE-CLASS
> >> instances, both of which can be printed readably?
> >>
> >> STRUCTURE-CLASSes even support (single) inheritance and generic function
> >> methods can specialize on them, in case you want to retain that
> >> functionality.
> >>
> >> Cheers,
> >> Pillsy
> >
> > I have not made myself clear. In each of my games I try to use different
> > tecniques and different approaches. I want to use classes it is just the
> > way it stores itself I don't like. In particular I don't like write-
> > string and would have prefered princ.
> >
> > Basically just one huge line. To pprint it would look nice but would
> > require the entire structure to be held in RAM and that is just to
> > wastfull. (Call me old fashioned, but I hate waste.)
>
> I would avoid using write-string to print something that will be read
> back. Build a sexp, and print it. (Avoid pprint for serialization
> since it's slower).

Backquote is useful for this:

(defmethod store-expression ((item tree-node))
`(make-instance 'tree-node
:item ,(store-expression (item item))
,@(awhen (left-child item)
`(:left-child ,(store-expression it)))
,@(awhen (right-child item)
`(:right-child ,(store-expression it)))))

(defmethod store ((item tree-node) stream)
(prin1 (store-expression item) stream))

You might also want to look at PRINT-OBJECT methods.

--
Barry Margolin, barmar(a)alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***