[Openmcl-devel] [off-topic] Adding a slot to a class using the MOP
pc at p-cos.net
Mon Apr 22 23:28:59 PDT 2013
As I said, in principle adding a slot programmatically is fine. However, it's like shooting at a bird with a cannon. This is not because you have the "wrong" idea about doing it like that, but it's because the way the CLOS MOP is specified makes this an especially heavy-weight operation. I would prefer if the CLOS MOP would have made this easier, but alas, it's not.
It's heavy-weight, because you have to read the current set of slot definitions from a class; understand them, which may not be trivial if other metaclasses are mixed in that you don't know about; and issue the redefinition by way of ensure-class, which is the programmatic version of the defclass macro. In a multi-threaded environment, this all becomes unsafe, because strictly speaking you need to take a lock around all these operations, but CLOS doesn't provide any publicly accessible lock that could help you, and defining your own lock won't help you either if other libraries also want to programmatically add slots.
What you probably want is that users can write class definitions, either of the following form:
(defclass c0 ()
( … slots … (some-slot :key nil)))
…or of the following form:
(defclass c1 ()
( … slots … (some-slot :key t)))
This is all perfectly possible without adding slots programmatically. You need to do the following:
1) Define your own class metaobject class.
2) Define your own direct slot definition and effective slot definition classes.
3) The direct slot definition understand the :key parameter and sets a boolean slot in direct slot definition objects.
4) Depending on that boolean value, you either generate a standard-effective-slot-definition or a key-effective-slot-definition. (It's better here not to use a boolean value, because for standard-effective-slot-definition, CLOS can make a couple of optimizations that it can't for user-defined effective slot definitions.)
5) You define methods on slot-value-using-class and friends.
All of these meta-definitions need to be linked to each other via several steps in the class definition protocol. It's all a bit difficult to get through when you do this for the first time, but will be obvious in retrospect. ;)
On 23 Apr 2013, at 00:26, Ron Garret <ron at flownet.com> wrote:
> I'm writing a persistent object store, where the user can choose to provide their own primary key or use a system-generated UID. If they use the system-generated UID then it has to be stored somewhere, and a slot in the object being stored seems like the obvious place. But I'm open to suggestions. I actually have a workaround, which is to just require the user to provide a slot to store the key even if it's system generated, but that seems inelegant. It seems to me that this sort of thing ought not to be as hard as it apparently is.
> Why would adding a slot programmatically cause any more problems that redefining a class with a different repertoire of slots? Isn't the whole point of the MOP to be able to do (among other things) exactly that? Isn't that why update-instance-for-redefined-class exists?
> On Apr 22, 2013, at 1:23 PM, Pascal Costanza wrote:
>> Check out AspectL, it provides exactly what you want.
>> However, it's also worthwhile spending some time on thinking about whether there is a better design for your problem. Adding slots like this creates a lot of problems. Maybe a typical hash table based meta class already provides what you need...
>> Sent from my iPad
>> On 22 Apr 2013, at 19:32, Ron Garret <ron at flownet.com> wrote:
>>> Apologies for the non-CCL-related question, but c.l.l. is slow today and I'm really stuck on this.
>>> I need to dynamically add a slot to a class using the MOP. There doesn't seem to be a standard add-slot method, so I figure I need to use something like ensure-class. To do that, I need to reconstruct the argument to :direct-slots from the existing class definition so I can add a slot without disturbing the existing slots. Before I went down this rabbit hole I thought I'd ask: is there a better/easier way to do this? Surely I'm not the first person to want to do this.
>>> Many thanks,
>>> Openmcl-devel mailing list
>>> Openmcl-devel at clozure.com
More information about the Openmcl-devel