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?
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
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.
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/
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
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.
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 >
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.
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
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))))
>
>
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)
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
"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.
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
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.
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/
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.
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.
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/
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
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.
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 >
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?
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
"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