Re: calling MAKE-INSTANCE on a structure-class
On 12/24/15 Dec 24 -1:57 PM, Pascal J. Bourguignon wrote:
>
>
>
> On 24/12/15 20:34, Anthony Fairchild wrote:
>> I'm trying to get the current version of CL-SDL2 to work in Lispworks
>> 7 and I ran into an issue where MAKE-INSTANCE is being called on a
>> structure class. For example, this works in SBCL and CCL:
>>
>> CL-USER> (defstruct foo)
>> FOO
>> CL-USER> (make-instance (find-class 'foo))
>> #S(FOO)
>> CL-USER> (make-instance 'foo)
>> #S(FOO)
>>
>> When running the same code in Lispworks 7 I get:
>>
>> No applicable methods for #<STANDARD-GENERIC-FUNCTION MAKE-INSTANCE
>> 4100096004> with args (#<STRUCTURE-CLASS FOO 4020352373>)
>>
>> I cannot find anything in the CLHS indicating that structures can be
>> instantiated with MAKE-INSTANCE so I'm not sure if this is a bug in
>> Lispworks or just a feature of SBCL/CCL.
>>
>> Any ideas?
>
> There's nothing in the CLHS that prevents structures to be implemented
> as CLOS classes either.
>
> But it is not conforming, for a program to depend on it.
> This CL-SDL2 library is not conforming! It should not have been called
> CL- something!
>
> The only way to create a structure is to call one of the structure
> constructors (or one of the structure copiers), that can be declared in
> the defstruct structure options; by default, it's MAKE-FOO for a
> structure named FOO.
>
>
> Now, you have basically two choices:
>
> - either make the code conforming by replacing the calls to
> make-instance to calls to make-foo; but there may have other places
> where they have taken advantage of structures as CLOS objects; notably,
> the structure accessors are not (necessarily) generic functions! So you
> may prefer to:
>
> - implement a DEFSTRUCT macro that will define CLOS classes instead, and
> shadow CL:DEFSTRUCT, to use it instead. Depending on how packages are
> used by the source base, this may be more or less work, and it is also
> indiscriminate since it would apply to all the structures defined in
> those packages, but it may be preferable to do that. Notice that
> DEFSTRUCT is not a trivial macro (it defines a lot of functions,
> computing a lot of names, and you must be careful with case, and
> packages where those symbols are interned), and there's a big stubbling
> block: :INCLUDE may refer structures that have not been defined with
> your DEFSTRUCT macro (and therefore that are NOT CLOS classes). I guess
> you can fall back to CL:DEFSTRUCT if there's an :INCLUDE referencing a
> structure you don't know and have generated as a DEFCLASS.
Note that this can be *conditionally* implemented. You can retain code
that uses MAKE-INSTANCE on structure classes for those implementations
that you know to support it.
I don't know who wrote this, or what their motivations were, but
replacing all structures with CLOS objects *might* have an adverse
effect on the efficiency of the code, so you might not want to replace
structures with classes.
Note also that you might not have to replace calls to MAKE-INSTANCE with
calls to make-foo -- the MOP says MAKE-INSTANCE is a generic function,
so you could add EQL methods for the (names of) the structure classes
you need, again, conditionally compiling for those lisps that need them.
The accessors might be more of a nuisance, and require some macrology,
but this would depend on whether you really rely on them being treated
as GFs. If someone's fussed about efficiency, my guess is that they
would be using the accessors in ways that are consistent with them not
being GFs.
hth
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html