CLOS doesn't have the concept of "this" or "self" because through the use of generic functions, whatever instance is being acted upon is passed as an argument.
So, given your example with the accessor mn-pai
:
(setf instance (make-instance 'mn))
(mn-pai instance 1)
Here, instance
is passed as an argument to the accessor.
If you created a method:
(defmethod inc-pai (an-mn amount)
(incf (mn-pai an-mn) amount))
Again, you see the instance is passed in as the first argument. So, there's always an explicit argument that you use.
Now consider:
(defmethod inc-both (an-mn another-mn amount)
(incf (mn-pai an-mn) amount)
(incf (mn-pai another-mn) amount))
So, in a normal class based system, where would you put this method? In a Utility class? Is this a "mn" class method? It sort of defies ready categorization.
Now consider:
(defclass mn2 ()
((pai :accessor mn2-pai)))
if we were to do this:
(setf an-mn (make-instance 'mn))
(setf an-mn2 (make-instance 'mn2))
(inc-both an-mn an-mn2)
The second line would fail, as mn2 does not have a mn-pai
accessor.
However, this would work:
(defmethod inc-both2 (an-mn another-mn amount)
(incf (slot-value 'pai an-mn) amount)
(incf (slot-value 'pai another-mn) amount))
Because the slot-value
is the primitive accessor for CLOS, and both classes have a slot named pai
. But, then you don't get to call the accessor function. Rather you're setting the slot directly. Probably not what you want. And, of course, the names are coincidence. There's no relationship between the classes save their similar names and a shared slot name.
But you can then do this:
(defmethod inc-both ((mn an-mn) (mn2 another-mn) amount)
(incf (mn-pai an-mn) amount)
(incf (mn-pai2 another-mn) amount))
This works because the runtime will dispatch based on the types of the parameters. We "know" another-mn
is an instance of mn2
because we told the system that it must be when we qualified the argument.
But, again, you can see how in a class based system, there's no "place" for this kind of method. We typically just create a Utility class of some kind and stick these in there, or a regular function in the global namespace.
While CLOS has classes, it's not really a class based system.
This also comes up in multi-inheritance scenarios (which CLOS supports). Who is "self" then?