From: javuchi
Subject: Using CLOS or not
Date: 
Message-ID: <1134670038.910908.68700@g14g2000cwa.googlegroups.com>
I'm going to implement a system in which I do need objects, but not
classes. I mean: a system in which I am going to define a lot of
objects with methods, and relations between them, but I only need one
instance of each object, no more.
Can you recommend using CLOS is this situation?

From: Kenny Tilton
Subject: Re: Using CLOS or not
Date: 
Message-ID: <9ajof.12063$Ys4.11770@twister.nyc.rr.com>
javuchi wrote:
> I'm going to implement a system in which I do need objects, but not
> classes. I mean: a system in which I am going to define a lot of
> objects with methods, and relations between them, but I only need one
> instance of each object, no more.
> Can you recommend using CLOS is this situation?
> 

The short answer is, Yes.

The nosy answer is: Well, you have not really told us anything yet. The 
above is just how you have already decided to handle some functional 
requirement unknown to us. It is like saying you have decided to connect 
two things by tying them together with rope, and is a bowline the right 
knot? The bowline is a fine knot, but....

My question would be, how did you get to the idea of using singletons 
(classes with one instance) to solve what problem?

kt
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134686076.518482.62100@o13g2000cwo.googlegroups.com>
Kenny Tilton ha escrito:

> The nosy answer is: Well, you have not really told us anything yet. The
> above is just how you have already decided to handle some functional
> requirement unknown to us. It is like saying you have decided to connect
> two things by tying them together with rope, and is a bowline the right
> knot? The bowline is a fine knot, but....

I need to define and interconnect objects. Each object represent a
"thing", and their methods the way to interact with other objects. But
every object is so particular that having inheritance is not practical.
Defining the class first and then the implementation for each one might
be a hell, as I need to write a lot of them. I know I can resolv this
by defining a new macro which automates the proccess, but I ask myself
if the resulting code of the expansion  would be fast enough (that is,
if CLOS has good performance with singletons).

> My question would be, how did you get to the idea of using singletons
> (classes with one instance) to solve what problem?

Not yet. I even didn't knew that "singletons" exists.

Bye.
From: Pascal Costanza
Subject: Re: Using CLOS or not
Date: 
Message-ID: <40eancF184h0kU1@individual.net>
javuchi wrote:

> I need to define and interconnect objects. Each object represent a
> "thing", and their methods the way to interact with other objects. But
> every object is so particular that having inheritance is not practical.
> Defining the class first and then the implementation for each one might
> be a hell, as I need to write a lot of them. I know I can resolv this
> by defining a new macro which automates the proccess, but I ask myself
> if the resulting code of the expansion  would be fast enough (that is,
> if CLOS has good performance with singletons).

You probably don't need to worry about performance. Most CLOS 
implementations are very efficient.

If you really need just singletons, what you can do is to use the CLOS 
classes themselves as objects. If all your slots have :allocation 
:class, that's what you effectivly get. Example:

(defclass pascal ()
   ((name :accessor name
          :initform "Pascal Costanza"
          :allocation :class)
    (address :accessor address
             :initform "Brussels"
             :allocation :class)))

(defmethod print-info ((object pascal))
   (print (name object))
   (print (address object)))

The only thing is that you need to access the class object indirectly. 
If you have the MOP available, you can do this via the class-prototype:

(print-info (class-prototype (find-class 'pascal)))

If you don't have the MOP in your preferred implementation, the 
following should do:

(defvar *class-prototypes* (make-hash-table))

(defun class-prototype (class)
   (or (gethash class *class-prototypes*)
       (setf (gethash class *class-prototypes*)
             (allocate-instance class))))

You can abbreviate (class-prototype (find-class ...)) and defclass 
defining form for "prototypical objects" with macros.

In the way described above, you could even have inheritance between objects.


However, I doubt that you will really not end up using "real" objects.


If you're interested in alternative object models for Common Lisp, you 
can find some at 
http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/oop/non_clos/0.html

However, most of them don't seem to have been updated in quite a while.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Kenny Tilton
Subject: Re: Using CLOS or not
Date: 
Message-ID: <Stoof.7966$i1.7399@news-wrt-01.rdc-nyc.rr.com>
javuchi wrote:
> Kenny Tilton ha escrito:
> 
> 
>>The nosy answer is: Well, you have not really told us anything yet. The
>>above is just how you have already decided to handle some functional
>>requirement unknown to us. It is like saying you have decided to connect
>>two things by tying them together with rope, and is a bowline the right
>>knot? The bowline is a fine knot, but....
> 
> 
> I need to define and interconnect objects. Each object represent a
> "thing", and their methods the way to interact with other objects. But
> every object is so particular that having inheritance is not practical.
> Defining the class first and then the implementation for each one might
> be a hell, as I need to write a lot of them. I know I can resolv this
> by defining a new macro which automates the proccess, but I ask myself
> if the resulting code of the expansion  would be fast enough (that is,
> if CLOS has good performance with singletons).

I see. Yes, macrology can hide the mechanics, whatever you choose for 
mechanics. In re performance, I am no expert but I think you would need 
an awful lot of classes to bog down the GF dispatch. I would not worry 
about performance in this case until I saw something slow. That said...

You could make one class, give it a slot "behavior", and then store 
there an anonymous function (lambda ...), different perhaps for each 
instance. These lambdas can be supplied when you make each instance, and 
then they can capture lexical variables so even instances spawned with 
the same lambda end up with different behavior, as dictated by the 
captured variable values.

Now you can use CLOS classes normally, where your instances really do 
fall into different useful subsets aka types aka, well, classes.

Digression: Now since you mention interaction, this sounds like the kind 
of application where my Cells project 
http://common-lisp.net/project/cells/ would really pay off, since the 
more interactions you have, the more complexity you get. Exponentially 
so. And in your case it sounds like you have a large quantity of objects 
as well as them having different rules.

But never mind that. The key is that I think this is a case for 
anonymous functions, not singletons. The latter is just overkill when 
what you really want is per-instance variation.

kt
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134698087.248671.54070@f14g2000cwb.googlegroups.com>
Kenny Tilton ha escrito:

> I see. Yes, macrology can hide the mechanics, whatever you choose for
> mechanics. In re performance, I am no expert but I think you would need
> an awful lot of classes to bog down the GF dispatch. I would not worry
> about performance in this case until I saw something slow. That said...
>
> You could make one class, give it a slot "behavior", and then store
> there an anonymous function (lambda ...), different perhaps for each
> instance. These lambdas can be supplied when you make each instance, and
> then they can capture lexical variables so even instances spawned with
> the same lambda end up with different behavior, as dictated by the
> captured variable values.
>
> Now you can use CLOS classes normally, where your instances really do
> fall into different useful subsets aka types aka, well, classes.
>
> Digression: Now since you mention interaction, this sounds like the kind
> of application where my Cells project
> http://common-lisp.net/project/cells/ would really pay off, since the
> more interactions you have, the more complexity you get. Exponentially
> so. And in your case it sounds like you have a large quantity of objects
> as well as them having different rules.
>
> But never mind that. The key is that I think this is a case for
> anonymous functions, not singletons. The latter is just overkill when
> what you really want is per-instance variation.


A *dirty* example code of what I need:

(setf *my-objects*
      `((object1 (:one-method ,#'(lambda (self x) (setf (getf self
:one-property) x))
		  :one-property "hello"))
	(object2 (:other-method ,#'(lambda (self) (format t "another"))
		  :one-property "bye"))))

I need to write lot of them, so they might be fast and concise to
write, and to access their methods... but I won't like true methods in
the sense of CLOS, just a way to acces them anonymously, as they are
not going to be used by a "human" programmer, but just inside a
mechanism of automatic object creation. I only need to write a large
base of them, but the rest, which are supposed to be thousands, are
going to be generated automatically by a program. I need a way to write
these objects with theirs functions to disk... as I asked some days
ago.
So: I need a way to make me easy to create the base, and a way for this
to be managed easyly and fast by automatic processes.
This object system is so simple that I doubt if CLOS would be needed.
Elsewhere, I don't know if I'll end up needing more capabilities of
this system. If I manage to hide CLOS implementation so it is easy for
me to write the base, and I have the garantiee that CLOS  will not
interfere too much in performance, I may use it.
Indeed, I must admit that I'm still far from being a Lisp expert, as
you may suppose reading my messagges... I've got the idea and
understand the incredible power of Lisp, but don't know really all of
its tricks... CLOS knowledge is my main fault at the moment.... as I
say sometimes: I'm a programmer in mind, but a really bad
implementator. ;) I just discovered Lisp two months ago and am so
impressed... it is not only a tool, it is a different way of thinking
computation.

Have fun.
From: Wade Humeniuk
Subject: Re: Using CLOS or not
Date: 
Message-ID: <ujqof.4169$wg4.2669@edtnps84>
javuchi wrote:
> Kenny Tilton ha escrito:
> 
> 
>>I see. Yes, macrology can hide the mechanics, whatever you choose for
>>mechanics. In re performance, I am no expert but I think you would need
>>an awful lot of classes to bog down the GF dispatch. I would not worry
>>about performance in this case until I saw something slow. That said...
>>
>>You could make one class, give it a slot "behavior", and then store
>>there an anonymous function (lambda ...), different perhaps for each
>>instance. These lambdas can be supplied when you make each instance, and
>>then they can capture lexical variables so even instances spawned with
>>the same lambda end up with different behavior, as dictated by the
>>captured variable values.
>>
>>Now you can use CLOS classes normally, where your instances really do
>>fall into different useful subsets aka types aka, well, classes.
>>
>>Digression: Now since you mention interaction, this sounds like the kind
>>of application where my Cells project
>>http://common-lisp.net/project/cells/ would really pay off, since the
>>more interactions you have, the more complexity you get. Exponentially
>>so. And in your case it sounds like you have a large quantity of objects
>>as well as them having different rules.
>>
>>But never mind that. The key is that I think this is a case for
>>anonymous functions, not singletons. The latter is just overkill when
>>what you really want is per-instance variation.
> 
> 
> 
> A *dirty* example code of what I need:
> 
> (setf *my-objects*
>       `((object1 (:one-method ,#'(lambda (self x) (setf (getf self
> :one-property) x))
> 		  :one-property "hello"))
> 	(object2 (:other-method ,#'(lambda (self) (format t "another"))
> 		  :one-property "bye"))))
> 
> I need to write lot of them, so they might be fast and concise to
> write, and to access their methods... but I won't like true methods in
> the sense of CLOS, just a way to acces them anonymously, as they are
> not going to be used by a "human" programmer, but just inside a
> mechanism of automatic object creation. I only need to write a large
> base of them, but the rest, which are supposed to be thousands, are
> going to be generated automatically by a program. I need a way to write
> these objects with theirs functions to disk... as I asked some days
> ago.

Try this, it is heavy handed, but the anonymous functions are stored
in their source form.  The following way uses eval to execute them
on the arguments.

(defparameter *my-objects*
       `((object1 (:one-method
                   (lambda (self x)
                     (setf (getf (cadr self) :one-property) x))
		  :one-property "hello"))
	(object2 (:other-method (lambda (self) (format t "another"))
		  :one-property "bye"))))

(defun execute-self-method (object-id method-id &rest args)
   (let* ((object (assoc object-id *my-objects*)))
     (if object
         (let ((method (getf (cadr object) method-id)))
           (if method
               (apply (eval method) object args)
             (error "No Method ~A" method-id)))
       (error "No Object ~A" object-id))))

CL-USER 5 > *my-objects*
((OBJECT1 (:ONE-METHOD (LAMBDA (SELF X) (SETF (GETF (CADR SELF) :ONE-PROPERTY) X)) 
:ONE-PROPERTY "hello")) (OBJECT2 (:OTHER-METHOD (LAMBDA (SELF) (FORMAT T "another")) 
:ONE-PROPERTY "bye")))

CL-USER 6 > (execute-self-method 'object1 :one-method 200)
200

CL-USER 7 > *my-objects*
((OBJECT1 (:ONE-METHOD (LAMBDA (SELF X) (SETF (GETF (CADR SELF) :ONE-PROPERTY) X)) 
:ONE-PROPERTY 200)) (OBJECT2 (:OTHER-METHOD (LAMBDA (SELF) (FORMAT T "another")) 
:ONE-PROPERTY "bye")))

CL-USER 8 > (execute-self-method 'object2 :other-method)
another
NIL

CL-USER 9 >
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134745261.250007.300770@z14g2000cwz.googlegroups.com>
Wade Humeniuk ha escrito:

> Try this, it is heavy handed, but the anonymous functions are stored
> in their source form.  The following way uses eval to execute them
> on the arguments.

This is more or less what I need. Having the function written and not
pre-evaluated (using #') allows me to easyly write it to disk. One
related problem may be its performance. I suppose that "eval" is
executing interpreted code, am I wrong?
If it does, then I must add a compile sentence while loading the file,
and manage to have it already cached for not having to wait until it is
compiled every time I use the method.
The problem here would be: how to write to disk already compiled
functions? May I need to have duplicate methods, one compiled and the
same one in its source form in another place? This is something I have
to investigate.

Thinking about it, I could even hide the "self" statment, and even the
lambda one, so prototyping of the base system would be faster and
easier.


> (defparameter *my-objects*
>        `((object1 (:one-method
>                    (lambda (self x)
>                      (setf (getf (cadr self) :one-property) x))
> 		  :one-property "hello"))
> 	(object2 (:other-method (lambda (self) (format t "another"))
> 		  :one-property "bye"))))
>
> (defun execute-self-method (object-id method-id &rest args)
>    (let* ((object (assoc object-id *my-objects*)))
>      (if object
>          (let ((method (getf (cadr object) method-id)))
>            (if method
>                (apply (eval method) object args)
>              (error "No Method ~A" method-id)))
>        (error "No Object ~A" object-id))))


Have fun.
From: Wade Humeniuk
Subject: Re: Using CLOS or not
Date: 
Message-ID: <t4Cof.2059$ic1.832@edtnps90>
javuchi wrote:
> Wade Humeniuk ha escrito:
> 
> 
>>Try this, it is heavy handed, but the anonymous functions are stored
>>in their source form.  The following way uses eval to execute them
>>on the arguments.
> 
> 
> This is more or less what I need. Having the function written and not
> pre-evaluated (using #') allows me to easyly write it to disk. One
> related problem may be its performance. I suppose that "eval" is
> executing interpreted code, am I wrong?
> If it does, then I must add a compile sentence while loading the file,
> and manage to have it already cached for not having to wait until it is
> compiled every time I use the method.
> The problem here would be: how to write to disk already compiled
> functions? May I need to have duplicate methods, one compiled and the
> same one in its source form in another place? This is something I have
> to investigate.
> 

Caching  could work.  However if you change the method its cached version should be
wiped.  Think of it as the JIT compile approach.  The following code would need
more error checks in real life to prevent problems.

(defparameter *my-objects*
       `((object1 (:one-method
                   (lambda (self x)
                     (setf (getf (cadr self) :one-property) x))
           :one-property "hello"))
     (object2 (:other-method (lambda (self) (declare (ignore self)) (format t "another"))
           :one-property "bye"))))

(defvar *my-object-method-cache* (make-hash-table :test #'equal))

(defun execute-self-method (object-id method-id &rest args)
   (let* ((object (assoc object-id *my-objects*))
          (method
           (when object
             (gethash (cons object-id method-id) *my-object-method-cache*
                      (let* ((source-method (getf (cadr object) method-id))
                             (evaled-method (when source-method (eval source-method)))
                             (compiled-method (when (functionp evaled-method) (compile nil 
evaled-method))))
                        (when compiled-method
                          (setf (gethash (cons object-id method-id) 
*my-object-method-cache*) compiled-method)))))))
     (if object
         (if method
             (apply method object args)
           (error "No Method ~A" method-id))
       (error "No Object ~A" object-id))))

CL-USER 7 > (execute-self-method 'object1 :one-method 200)
200

CL-USER 8 > *my-objects*
((OBJECT1 (:ONE-METHOD (LAMBDA (SELF X) (SETF (GETF (CADR SELF) :ONE-PROPERTY) X)) 
:ONE-PROPERTY 200)) (OBJECT2 (:OTHER-METHOD (LAMBDA (SELF) (FORMAT T "another")) 
:ONE-PROPERTY "bye")))

CL-USER 9 > *my-object-method-cache*
#<EQUAL Hash Table{1} 21458E14>

CL-USER 11 > (execute-self-method 'object1 :one-method 400)
400

CL-USER 12 > *my-objects*
((OBJECT1 (:ONE-METHOD (LAMBDA (SELF X) (SETF (GETF (CADR SELF) :ONE-PROPERTY) X)) 
:ONE-PROPERTY 400)) (OBJECT2 (:OTHER-METHOD (LAMBDA (SELF) (FORMAT T "another")) 
:ONE-PROPERTY "bye")))

CL-USER 13 > *my-object-method-cache*
#<EQUAL Hash Table{1} 21458E14>

CL-USER 14 > (gethash (cons 'object1 :one-method) *my-object-method-cache*)
#<function 11 20688DF2>
T

CL-USER 15 > (disassemble *)
; Loading fasl file C:\Program Files\Xanalys\LispWorks\lib\4-3-0-0\modules\util\disass.fsl
; Loading fasl file C:\Program 
Files\Xanalys\LispWorks\lib\4-3-0-0\patches\disassembler\0001\0001.fsl
; Loaded public patch DISASSEMBLER 1.1

; Loading fasl file C:\Program Files\Xanalys\LispWorks\lib\4-3-0-0\modules\memory\findptr.fsl
2168944A:
        0:      3B25BC150020     cmp   esp, [200015BC]  ; T
        6:      7639             jbe   L1
        8:      80FD02           cmpb  ch, 2
       11:      7534             jne   L1
       13:      55               push  ebp
       14:      89E5             move  ebp, esp
       16:      50               push  eax
       17:      50               push  eax
       18:      8B4508           move  eax, [ebp+8]
       21:      E83E9533FF       call  209C29A2         ; #<function SEQ::CADR-1ARG 209C29A2>
       26:      50               push  eax
       27:      68640B3221       push  21320B64         ; :ONE-PROPERTY
       32:      B503             moveb ch, 3
       34:      8B45FC           move  eax, [ebp-4]
       37:      FF1560B01220     call  [2012B060]       ; COMMON-LISP::ADDPROP
       43:      8945F8           move  [ebp-8], eax
       46:      FF7508           push  [ebp+8]
       49:      8B45F8           move  eax, [ebp-8]
       52:      E82FF264FF       call  20CD86B2         ; #<function SEQ::SET-CADR-2ARG 
20CD86B2>
       57:      8B45FC           move  eax, [ebp-4]
       60:      FD               std
       61:      C9               leave
       62:      C20400           ret   4
L1:   65:      E8D2E29BFE       call  20047762         ; #<function 20047762>
NIL

CL-USER 19 > (execute-self-method 'object2 :other-method)
Self Method COMPILED-CODE
another
NIL

CL-USER 20 > *my-object-method-cache*
#<EQUAL Hash Table{2} 2166A1DC>

CL-USER 21 >

Wade
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134754585.917011.205360@z14g2000cwz.googlegroups.com>
Wade Humeniuk ha escrito:

> Caching  could work.  However if you change the method its cached version should be
> wiped.  Think of it as the JIT compile approach.  The following code would need
> more error checks in real life to prevent problems.

Thanks, Wade. I promess to complete your object system and publish it
here. How about calling it SOS (singleton object system)? ;)

Have fun.




> (defparameter *my-objects*
>        `((object1 (:one-method
>                    (lambda (self x)
>                      (setf (getf (cadr self) :one-property) x))
>            :one-property "hello"))
>      (object2 (:other-method (lambda (self) (declare (ignore self)) (format t "another"))
>            :one-property "bye"))))
>
> (defvar *my-object-method-cache* (make-hash-table :test #'equal))
>
> (defun execute-self-method (object-id method-id &rest args)
>    (let* ((object (assoc object-id *my-objects*))
>           (method
>            (when object
>              (gethash (cons object-id method-id) *my-object-method-cache*
>                       (let* ((source-method (getf (cadr object) method-id))
>                              (evaled-method (when source-method (eval source-method)))
>                              (compiled-method (when (functionp evaled-method) (compile nil
> evaled-method))))
>                         (when compiled-method
>                           (setf (gethash (cons object-id method-id)
> *my-object-method-cache*) compiled-method)))))))
>      (if object
>          (if method
>              (apply method object args)
>            (error "No Method ~A" method-id))
>        (error "No Object ~A" object-id))))
From: Wade Humeniuk
Subject: Re: Using CLOS or not
Date: 
Message-ID: <U4Gof.358$h86.57@edtnps89>
javuchi wrote:
> Wade Humeniuk ha escrito:
> 
> 
>>Caching  could work.  However if you change the method its cached version should be
>>wiped.  Think of it as the JIT compile approach.  The following code would need
>>more error checks in real life to prevent problems.
> 
> 
> Thanks, Wade. I promess to complete your object system and publish it
> here. How about calling it SOS (singleton object system)? ;)
> 
> Have fun.

Hmm, I already have an object system published, MOS, (Macroless Object System),
its part of SLIB (the Scheme Library).

To really make this an object system, its needs a formal defintion (meaning code)
of object.  For a name I think CEOS (Closed Externalizable Object System). :)

Wade



> 
> 
> 
> 
> 
>>(defparameter *my-objects*
>>       `((object1 (:one-method
>>                   (lambda (self x)
>>                     (setf (getf (cadr self) :one-property) x))
>>           :one-property "hello"))
>>     (object2 (:other-method (lambda (self) (declare (ignore self)) (format t "another"))
>>           :one-property "bye"))))
>>
>>(defvar *my-object-method-cache* (make-hash-table :test #'equal))
>>
>>(defun execute-self-method (object-id method-id &rest args)
>>   (let* ((object (assoc object-id *my-objects*))
>>          (method
>>           (when object
>>             (gethash (cons object-id method-id) *my-object-method-cache*
>>                      (let* ((source-method (getf (cadr object) method-id))
>>                             (evaled-method (when source-method (eval source-method)))
>>                             (compiled-method (when (functionp evaled-method) (compile nil
>>evaled-method))))
>>                        (when compiled-method
>>                          (setf (gethash (cons object-id method-id)
>>*my-object-method-cache*) compiled-method)))))))
>>     (if object
>>         (if method
>>             (apply method object args)
>>           (error "No Method ~A" method-id))
>>       (error "No Object ~A" object-id))))
> 
> 
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134777456.270515.125080@g47g2000cwa.googlegroups.com>
Wade Humeniuk ha escrito:

> Hmm, I already have an object system published, MOS, (Macroless Object System),
> its part of SLIB (the Scheme Library).
>
> To really make this an object system, its needs a formal defintion (meaning code)
> of object.  For a name I think CEOS (Closed Externalizable Object System). :)


You mean something like this?

1.- We want an object system in which there is not disctintion between
class and object. When you're writing a new object, you're writing its
instance at the same time, and its data and functions are fully ready
for use without having to instantiate anything. This has the side
effect that there is not inheritance, but there may be a way of copying
objects,
if we need.
2.- It should be easy to add new data to the objects, functions, or a
way to change both.
3.- At the moment, we are not interested in private data, but let the
door open for this feature in future versions.
4.- We are going to define systems or sets of objects. Each set is
stored in global variables, and it is enforced to use them.
5.- We are encourage to make the programmer to write up objects in the
more concise and easy way. This system is intended for letting the
programer
writing large amounts of objects.
6.- We want it to be fast, so it is able to manage thousands of objects
with theirs methods.
7.- Put here your suggestions.

Now an example:

Imagine we want to define an adventure game. There might be a lot of
objects in this game. Most of them are unique, or copy of others. So we
define a set of objects:

(defobjects *sos-game*
    (bottle
     (:size "small"
      :state "open"
      :color 'transparent
      :quantity 100
      :where 'living-room
      :action-drink (lambda (self)
		      (setf (self :quantity) 0))))
    (wiskey-bottle :copy-from 'bottle
     (:color 'red
      :where 'car))
    (car
     (:action-drive (lambda (self)
		      (if (= (other 'wiskey-bottle :quantity) 0)
			  (format t "You drunk just before driving, so you dead.")
			  (format t "Ok, driving to the pub."))))))


Somewhere in the program, we could make changes to objects:

(setf (property *sos-game* 'bottle :state) "closed")

But inside the object set we just use "other", not "property".  And
inside the object itself we just use "self". If we try to retrive a
non-existent property, we get nil.

Whenever we want to save the game state, we just do something like:

(save-objects *sos-game* "/tmp/my-game.sos")

And if we want to restore the game state, we just:

(restore-objects *sos-game* "/tmp/my-game.sos")

We could add new objects:

(add-object *sos-game* '(shoe (:size 44 :where 'bedroom)))

And remove them:

(del-object *sos-game* 'shoe)
From: Kenny Tilton
Subject: Re: Using CLOS or not
Date: 
Message-ID: <ikqof.7982$i1.4131@news-wrt-01.rdc-nyc.rr.com>
javuchi wrote:
> Kenny Tilton ha escrito:
> 
> 
>>I see. Yes, macrology can hide the mechanics, whatever you choose for
>>mechanics. In re performance, I am no expert but I think you would need
>>an awful lot of classes to bog down the GF dispatch. I would not worry
>>about performance in this case until I saw something slow. That said...
>>
>>You could make one class, give it a slot "behavior", and then store
>>there an anonymous function (lambda ...), different perhaps for each
>>instance. These lambdas can be supplied when you make each instance, and
>>then they can capture lexical variables so even instances spawned with
>>the same lambda end up with different behavior, as dictated by the
>>captured variable values.
>>
>>Now you can use CLOS classes normally, where your instances really do
>>fall into different useful subsets aka types aka, well, classes.
>>
>>Digression: Now since you mention interaction, this sounds like the kind
>>of application where my Cells project
>>http://common-lisp.net/project/cells/ would really pay off, since the
>>more interactions you have, the more complexity you get. Exponentially
>>so. And in your case it sounds like you have a large quantity of objects
>>as well as them having different rules.
>>
>>But never mind that. The key is that I think this is a case for
>>anonymous functions, not singletons. The latter is just overkill when
>>what you really want is per-instance variation.
> 
> 
> 
> A *dirty* example code of what I need:
> 
> (setf *my-objects*
>       `((object1 (:one-method ,#'(lambda (self x) (setf (getf self
> :one-property) x))
> 		  :one-property "hello"))
> 	(object2 (:other-method ,#'(lambda (self) (format t "another"))
> 		  :one-property "bye"))))
> 
> I need to write lot of them, so they might be fast and concise to
> write, and to access their methods... but I won't like true methods in
> the sense of CLOS, just a way to acces them anonymously, as they are
> not going to be used by a "human" programmer, but just inside a
> mechanism of automatic object creation. I only need to write a large
> base of them, but the rest, which are supposed to be thousands, are
> going to be generated automatically by a program. I need a way to write
> these objects with theirs functions to disk... as I asked some days
> ago.
> So: I need a way to make me easy to create the base, and a way for this
> to be managed easyly and fast by automatic processes.
> This object system is so simple that I doubt if CLOS would be needed.

I would not think of CLOS as some huge thing that needs to be avoided. 
That said, there is always defstruct or a kazillion other ways to have 
objects (in an abstract sense) without CLOS.

> Elsewhere, I don't know if I'll end up needing more capabilities of
> this system. If I manage to hide CLOS implementation so it is easy for
> me to write the base, and I have the garantiee that CLOS  will not
> interfere too much in performance, I may use it.

If I really really expect performance problems, I will use defstruct 
until the application proves to me I need the bigger hammer of CLOS.

> Indeed, I must admit that I'm still far from being a Lisp expert, as
> you may suppose reading my messagges... I've got the idea and
> understand the incredible power of Lisp, but don't know really all of
> its tricks...

There /are/ a lot (of tricks) and after a decade I can still learn new 
ones here on c.l.l. But in one respect CL is just a regular old 
programming language, so don't think too much about finding the mythical 
Lisp Way, just hack. My 2.


kt
From: Pascal Bourguignon
Subject: Re: Using CLOS or not
Date: 
Message-ID: <877ja5v8dg.fsf@thalassa.informatimago.com>
"javuchi" <·······@gmail.com> writes:

> Kenny Tilton ha escrito:
>
>> The nosy answer is: Well, you have not really told us anything yet. The
>> above is just how you have already decided to handle some functional
>> requirement unknown to us. It is like saying you have decided to connect
>> two things by tying them together with rope, and is a bowline the right
>> knot? The bowline is a fine knot, but....
>
> I need to define and interconnect objects. Each object represent a
> "thing", and their methods the way to interact with other objects. But
> every object is so particular that having inheritance is not practical.
> Defining the class first and then the implementation for each one might
> be a hell, as I need to write a lot of them. I know I can resolv this
> by defining a new macro which automates the proccess, but I ask myself
> if the resulting code of the expansion  would be fast enough (that is,
> if CLOS has good performance with singletons).
>
>> My question would be, how did you get to the idea of using singletons
>> (classes with one instance) to solve what problem?
>
> Not yet. I even didn't knew that "singletons" exists.

Have a look at garnet. It contains an prototype based object system
which may be what you want.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

This is a signature virus.  Add me to your signature and help me to live.
From: Kenny Tilton
Subject: Re: Using CLOS or not
Date: 
Message-ID: <Biuof.12708$Ys4.7044@twister.nyc.rr.com>
Pascal Bourguignon wrote:
> "javuchi" <·······@gmail.com> writes:
> 
> 
>>Kenny Tilton ha escrito:
>>
>>
>>>The nosy answer is: Well, you have not really told us anything yet. The
>>>above is just how you have already decided to handle some functional
>>>requirement unknown to us. It is like saying you have decided to connect
>>>two things by tying them together with rope, and is a bowline the right
>>>knot? The bowline is a fine knot, but....
>>
>>I need to define and interconnect objects. Each object represent a
>>"thing", and their methods the way to interact with other objects. But
>>every object is so particular that having inheritance is not practical.
>>Defining the class first and then the implementation for each one might
>>be a hell, as I need to write a lot of them. I know I can resolv this
>>by defining a new macro which automates the proccess, but I ask myself
>>if the resulting code of the expansion  would be fast enough (that is,
>>if CLOS has good performance with singletons).
>>
>>
>>>My question would be, how did you get to the idea of using singletons
>>>(classes with one instance) to solve what problem?
>>
>>Not yet. I even didn't knew that "singletons" exists.
> 
> 
> Have a look at garnet. It contains an prototype based object system
> which may be what you want.
> 

Two dead technologies. A better alternative might be had from Mr. 
Burdick if he has as threatened built a prototype system atop Cells, and 
is prepared to give it away.

But how do prototypes help give different behavior to different 
instances of the same class/prototype?

kt
From: Matthew D Swank
Subject: Re: Using CLOS or not
Date: 
Message-ID: <pan.2005.12.16.08.52.50.88444@c.net>
On Fri, 16 Dec 2005 07:47:45 +0000, Kenny Tilton wrote:

> But how do prototypes help give different behavior to different 
> instances of the same class/prototype?

Because methods are effectively tied to instances: there are no classes. 
I can create instances based on a prototype(s), add (or delete) methods
and use these instances as prototypes for other objects. There is no
(semantic) distinction between class/prototype and instance: they're just
all objects. 

One of the reasons early Smalltalk got rid of prototypical OO was that it
was thought to give the user _too_ much flexibility. Who ever heard of
Lisp rejecting something because it was too flexible.

Matt

-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: Pascal Costanza
Subject: Re: Using CLOS or not
Date: 
Message-ID: <40ferqF1a813dU1@individual.net>
Matthew D Swank wrote:

> On Fri, 16 Dec 2005 07:47:45 +0000, Kenny Tilton wrote:
> 
>>But how do prototypes help give different behavior to different 
>>instances of the same class/prototype?
> 
> Because methods are effectively tied to instances: there are no classes. 
> I can create instances based on a prototype(s), add (or delete) methods
> and use these instances as prototypes for other objects. There is no
> (semantic) distinction between class/prototype and instance: they're just
> all objects. 
> 
> One of the reasons early Smalltalk got rid of prototypical OO was that it
> was thought to give the user _too_ much flexibility. Who ever heard of
> Lisp rejecting something because it was too flexible.

Prototypes also have disadvantages. The notion of classification is a 
very powerful concept that is missing there, and if you take a look at 
what, for example, Self programmers do, you will notice that they 
reinvent the wheel by simulating classes. (Check out "traits" in papers 
and documentation related to Self. Note that they are very different 
from traits in Smalltalk.)

On the CLOS side, there is alredy quite a lot of flexibility similar to 
what you have in prototype-based languages. Adding and removing methods 
is doable by either using eql specializers, or using change-class on 
objects and using dynamically generated classes here. You can also 
relatively easily change inheritance hierarchies at runtime. You can 
even do all these things at runtime without the MOP, by using eval on 
the respective definition forms (defclass, defmethod, etc.).

The only real trade off between class-based and prototype-based systems 
is this:

- In prototype-based systems, you can devise role models in which an 
object can play the same role multiple times. Say, an person object can 
be multiple employees of different companies at the same time. This is 
hard to express with class-based languages.

- In class-based systems, you can define common state and behavior for 
numerous objects at the same time and have all the corresponding objects 
be affected immediately. In CLOS, there is even a well-defined protocol 
for handling this at runtime for already existing objects of a given 
class (cf. update-instance-for-redefined-class). This is something 
that's hard to express with prototype-based languages.

This is about the only real difference between prototypes and classes 
that I am aware of. (Note that "hard to express" means "hard to express 
without actually simulating the respective other approach".)

If neither of these two characteristics is of interest to you, it 
basically doesn't really matter whether you use prototypes or classes, 
except for syntactical differences (which can luckily easily be overcome 
in Lisp by writing a bunch of macros).


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Matthew D Swank
Subject: Re: Using CLOS or not
Date: 
Message-ID: <pan.2005.12.16.09.33.59.386099@c.net>
On Fri, 16 Dec 2005 10:14:34 +0100, Pascal Costanza wrote:


> 
> Prototypes also have disadvantages. 
>

Well, I was gushing a bit, but prototype based OO tends to get a bad
wrap. At least it used to. Javascript, though, may end up being the most
successful Object Oriented language of all time.

Matt

-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134746402.843181.43670@z14g2000cwz.googlegroups.com>
Pascal Costanza ha escrito:

> Prototypes also have disadvantages. The notion of classification is a
> very powerful concept that is missing there, and if you take a look at
> what, for example, Self programmers do, you will notice that they
> reinvent the wheel by simulating classes.

"Self" programmers even think that fixnums, strings, and of course
lists are instances of objects.
I think in the real life there is not really the existence of classes.
Everything is an instance of itself which might or not be similar to
other objects. Classes only exists in our imagination, really. I think
about classes as a way to easy create similar objects.
But, what happens when you do not need to create so similar objects,
and are all quite far different from eachother? Happens that you end up
thinking how to create a collection of classes which define your
system... and 2 days later you discover that made a mistake. I think
this is contrary to bottom-up programming, as encourage you to think
first how is to be organizated your system, before implementing it, and
not while implementing it.

Have fun.
From: Peter Seibel
Subject: Re: Using CLOS or not
Date: 
Message-ID: <m2d5jwzabl.fsf@gigamonkeys.com>
Pascal Costanza <··@p-cos.net> writes:

> Matthew D Swank wrote:
>
>> On Fri, 16 Dec 2005 07:47:45 +0000, Kenny Tilton wrote:
>> 
>>> But how do prototypes help give different behavior to different
>>> instances of the same class/prototype?
>> Because methods are effectively tied to instances: there are no
>> classes. I can create instances based on a prototype(s), add (or
>> delete) methods
>> and use these instances as prototypes for other objects. There is no
>> (semantic) distinction between class/prototype and instance: they're just
>> all objects. One of the reasons early Smalltalk got rid of
>> prototypical OO was that it
>> was thought to give the user _too_ much flexibility. Who ever heard of
>> Lisp rejecting something because it was too flexible.
>
> Prototypes also have disadvantages. The notion of classification is a
> very powerful concept that is missing there, and if you take a look at
> what, for example, Self programmers do, you will notice that they
> reinvent the wheel by simulating classes. (Check out "traits" in
> papers and documentation related to Self. Note that they are very
> different from traits in Smalltalk.)
>
> On the CLOS side, there is alredy quite a lot of flexibility similar
> to what you have in prototype-based languages. Adding and removing
> methods is doable by either using eql specializers, or using
> change-class on objects and using dynamically generated classes
> here. You can also relatively easily change inheritance hierarchies at
> runtime. You can even do all these things at runtime without the MOP,
> by using eval on the respective definition forms (defclass, defmethod,
> etc.).
>
> The only real trade off between class-based and prototype-based
> systems is this:
>
> - In prototype-based systems, you can devise role models in which an
>   object can play the same role multiple times. Say, an person object
>   can be multiple employees of different companies at the same
>   time. This is hard to express with class-based languages.
>
> - In class-based systems, you can define common state and behavior for
>   numerous objects at the same time and have all the corresponding
>   objects be affected immediately. In CLOS, there is even a
>   well-defined protocol for handling this at runtime for already
>   existing objects of a given class
>   (cf. update-instance-for-redefined-class). This is something that's
>   hard to express with prototype-based languages.
>
> This is about the only real difference between prototypes and classes
> that I am aware of. (Note that "hard to express" means "hard to
> express without actually simulating the respective other approach".)

The good news though, is that we don't have to fight about which is
better any more thanks to the Treaty of Orlando. ;-)

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Wade Humeniuk
Subject: Re: Using CLOS or not
Date: 
Message-ID: <74kof.1273$lv3.550@clgrps12>
javuchi wrote:
> I'm going to implement a system in which I do need objects, but not
> classes. I mean: a system in which I am going to define a lot of
> objects with methods, and relations between them, but I only need one
> instance of each object, no more.
> Can you recommend using CLOS is this situation?
> 

Define "object".  Sounds like you mean a collection of values, probably
a property/association list.

Wade
From: javuchi
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134686211.557967.124880@g47g2000cwa.googlegroups.com>
Wade Humeniuk ha escrito:

> javuchi wrote:
> > I'm going to implement a system in which I do need objects, but not
> > classes. I mean: a system in which I am going to define a lot of
> > objects with methods, and relations between them, but I only need one
> > instance of each object, no more.
> > Can you recommend using CLOS is this situation?
> >
>
> Define "object".  Sounds like you mean a collection of values, probably
> a property/association list.

Might be... but with methods. As commented in previus article from
myself, what I need are "singletons", but very simple in fact.
From: Wade Humeniuk
Subject: Re: Using CLOS or not
Date: 
Message-ID: <qQmof.30$h86.21@edtnps89>
javuchi wrote:
> Wade Humeniuk ha escrito:
> 
> 
>>javuchi wrote:
>>
>>>I'm going to implement a system in which I do need objects, but not
>>>classes. I mean: a system in which I am going to define a lot of
>>>objects with methods, and relations between them, but I only need one
>>>instance of each object, no more.
>>>Can you recommend using CLOS is this situation?
>>>
>>
>>Define "object".  Sounds like you mean a collection of values, probably
>>a property/association list.
> 
> 
> Might be... but with methods. As commented in previus article from
> myself, what I need are "singletons", but very simple in fact.  
> 

There is more than one possiblity here.  An object could be an alist, or
as simple as a uninterned symbol.  Use EQL method specialization for
singleton methods.  Symbols are nice because they have a plist "slot".
Allocating a "singleton" object could be as simple as using GENSYM and
then pushing properties onto the plist.

CL-USER 1 > (defparameter obj1 (list (cons 'name "wade")
                                      (cons 'address "calgary")))
OBJ1

CL-USER 2 > (defparameter obj2 (list (cons 'name "bob")
                                      (cons 'address "nowhere")))
OBJ2

CL-USER 3 > (defmethod lisper ((obj (eql obj1))) t)
#<STANDARD-METHOD LISPER NIL ((EQL ((NAME . "wade") (ADDRESS . "calgary")))) 20677274>

CL-USER 4 > (defmethod lisper ((obj (eql obj2))) nil)
#<STANDARD-METHOD LISPER NIL ((EQL ((NAME . "bob") (ADDRESS . "nowhere")))) 206842A4>

CL-USER 5 > (lisper obj1)
T

CL-USER 6 > (lisper obj2)
NIL

CL-USER 7 > (defparameter obj3 (gensym "OBJ"))
OBJ3

CL-USER 8 > obj3
#:OBJ519

CL-USER 9 > (defmethod name ((obj (eql obj3))) "kelly")
#<STANDARD-METHOD NAME NIL ((EQL #:OBJ519)) 20676D7C>

CL-USER 10 > (name obj3)
"kelly"

CL-USER 13 > (push (cons 'age 29) (symbol-plist obj3))
((AGE . 29) PKG::SYMBOL-NAME-STRING "OBJ519")

CL-USER 14 > (symbol-plist obj3)
((AGE . 29) PKG::SYMBOL-NAME-STRING "OBJ519")

CL-USER 15 > (push 'person-data (symbol-plist obj3))
(PERSON-DATA (AGE . 29) PKG::SYMBOL-NAME-STRING "OBJ519")

CL-USER 16 > (symbol-plist obj3)
(PERSON-DATA (AGE . 29) PKG::SYMBOL-NAME-STRING "OBJ519")

CL-USER 17 >
From: Rainer Joswig
Subject: Re: Using CLOS or not
Date: 
Message-ID: <joswig-7D0981.22235115122005@news-europe.giganews.com>
In article <·······················@g14g2000cwa.googlegroups.com>,
 "javuchi" <·······@gmail.com> wrote:

> I'm going to implement a system in which I do need objects, but not
> classes. I mean: a system in which I am going to define a lot of
> objects with methods, and relations between them, but I only need one
> instance of each object, no more.
> Can you recommend using CLOS is this situation?

Objects with methods? Instance of object? Are you sure?
From: bradb
Subject: Re: Using CLOS or not
Date: 
Message-ID: <1134688506.299377.261690@g47g2000cwa.googlegroups.com>
I would start with CLOS.  I find that I use it even for simple data
grouping, even if I don't define generic methods.  I suspect that you
are coming from an OO background where methods are closely associated
with the class & data.  CLOS is not like this.  I can only recommend
that you give CLOS a try.

Brad
From: Julian Stecklina
Subject: Re: Using CLOS or not
Date: 
Message-ID: <86slsqkseb.fsf@dellbeast.localnet>
"javuchi" <·······@gmail.com> writes:

> I'm going to implement a system in which I do need objects, but not
> classes. I mean: a system in which I am going to define a lot of
> objects with methods, and relations between them, but I only need one
> instance of each object, no more.
> Can you recommend using CLOS is this situation?

You might want to play around with KR which is a prototype-based
object system for Common Lisp.

http://www.cliki.net/KR


Regards,
-- 
Julian Stecklina

When someone says "I want a programming language in which I
need only say what I wish done," give him a lollipop. - Alan Perlis