Pascal Costanza wrote:
I need to look into a means to identify these problematic cases. Ugh.
MOP not standardized. Ugh ugh ugh ugh. I'll see if I can pilfer code from Closer-MOP to render ENSURE-CLASS accessible.
I wouldn’t recommend fiddling with ensure-class or ensure-class-using-class. It’s too hard to specialize methods correctly on those, and their portability across CL implementations is not very good.
If you want to implement checks on subclasses, it’s better to do this in initialize-instance / reinitialize-instance on metaclasses, but this requires that the subclasses also use those metaclasses, which may break other assumptions.
Sorry if this is a foolish question, but the class at issue here is OPERATION, whose metaclass is STANDARD-CLASS.
So am I correct in thinking I would need something like
(defmethod INITIALIZE-INSTANCE :BEFORE ((class standard-class) &key direct-superclasses) (when (member (find-class 'asdf:operation) direct-superclasses) ...handle my troublesome case...)))
where the primary portability challenge would be to make sure I have the right STANDARD-CLASS for the various implementations? [Hoping to cargo-cult that out of Closer-MOP.]
Is this the moral of this story: code that wishes to be backwards compatible and portable can NEVER change the class hierarchy above an API-visible class, because there is no *portable* way to detect when someone's code will be affected.
The interface a class exposes to its subclasses is an interface like any other, and yes, interface changes may have negative consequences. That’s correct for any kind of interfaces. It can be better to create new interfaces and leave the existing ones untouched if backwards compatibility is a major concern.
I don't believe that it's true that a class exposes an interface like any other.
If my library exposes an API in the form of a function call, then I may easily catch any invocation of that function call and, e.g., provide a deprecation warning, etc.
But I believe that your email indicates that we *cannot* portably identify cases where a user is extending a class that the library exposes.
Am I wrong about this? If so, please let me know! If not, I believe it shows that CLOS-based programs must be more cautious when exposing classes for extension, then when exposing other code artifacts.
Alas, now the cat is out of the bag, and we must figure out the best way to handle this specific case. Let me say again that I welcome all suggestions and guidance (like yours, above) in doing this.
Best, Robert