[HARLEQUIN][Common Lisp HyperSpec (TM)] [Previous][Up][Next]


Issue DEFSTRUCT-REDEFINITION Writeup

Status:	Passed (as amended) Jan 89 X3J13

Issue: DEFSTRUCT-REDEFINITION

References: DEFSTRUCT (CLtL pp 305-320)

Related-issues: DEFSTRUCT-ACCESS-FUNCTIONS-INLINE

Category: CLARIFICATION

Edit history: Version 1 by Skona Brittain 07/26/88

Version 2 by Larry Masinter 7-Jan-89

Version 3 by Masinter 6-Feb-89 as per Jan 89 X3J13 amendment

Problem Description:

The case of a structure type being redefined is not discussed in CLtL. Is

it legal to redefine a DEFSTRUCT? What happens to DEFSTRUCTS that :INCLUDE

the one defined. What things might be "wired in" in compiled code that

refered to the previous DEFSTRUCT?

Proposal: (DEFSTRUCT-REDEFINITION:ERROR):

The results of redefining a DEFSTRUCT structure are undefined.

Rationale:

DEFSTRUCT is intended as "the most efficient" structure class. DEFCLASS

allows much more flexible structures to be defined. Thus, implementations

should be free to "wire in" much of the behavior of a DEFSTRUCT into

compiled code.

The issue of redefinition should be addressed since there are always

consequences that affect use of the structures.

Current Practice:

None of KCL, Lucid, & Symbolics detect a redefinition.

Envos Medley goes to some effort to detect if a new structure is

"compatible" with the old -- e.g., slots might change names, initial

values, but, since the space allocated in an instance is determined by the

:TYPE, an incompatible set of :TYPE forms would cause old instances to be

marked "obsolete". (The TYPE-OF an old instance changes to **OBSOLETE**,

for example.)

Cost to Implementors:

This proposal attempts to be consistent with current practice.

Cost to Users:

It is doubtful that any current programs actually define structures more

than once. Thus, constraints on DEFSTRUCT redefinition primarily affect the

debugging environment.

Cost of Non-Adoption:

Confusion.

Benefits:

Clarity.

Aethetics:

Something that is not well-defined and leads to erratic behavior should be

explicitly considered an error.

Discussion:

Common implementation techniques may cause the following behavior if a

DEFSTRUCT is redefined:

If the new DEFSTRUCT is identical to the old DEFSTRUCT except for the

initialization forms for slots, previous structure objects probably can

continue to be accessed with previously compiled slot accessors. DEFSTRUCT

constructor, test functions are proclaimed INLINE, and if these have

changed, previously compiled occurrences of them may behave unpredictably.

If any change is made to the definiton of the slots (either in number,

name, or :TYPE), attempting to execute a slot accessor of the old

definition may behave unpredictably: if a slot name of the old definition

also names a slot of the new definition, any "compiled" code might use the

old definition instead.

DEFSTRUCT constructor, test functions may also be proclaimed INLINE, and

may behave unpredictably if previously compiled. In particular, a compiled

occurance of a constructor might have the previously slot initial values

"wired in".

If the new DEFSTRUCT differs from the old in any aspect other than the

initialization forms for slots, the results of attempting to access any old

instance might result in unspecified behavior. For example, if the size of

the structure became considerably shorter, an old accessor might "access

off the end" of an instance of a new object; it might signal an error or

have other unpredictable results.

Masinter supports this proposal. If users want more flexibility than

DEFSTRUCT allows, they should use DEFCLASS.

Some felt strongly that just saying it's an error to redefine a structure

but not requiring the error to be signalled will cause users to be confused

by the differing seemingly erratic behavior and code.

Programming environments are allowed, encouraged, etc. to allow such

redefinition, perhaps with warning messages. It is beyond the scope of the

language standard to define those interactions, except to note that they

are not portable.

Here's an example where reexecuting an EQUAL DEFSTRUCT might result in

different behavior:

(defvar *token-counter* 0)

(defstruct token (cookie '("unique-string")) (counter (incf

*token-counter*)))

(defvar *first-token* (make-token))

(eql (token-cookie *first-token*) (token-cookie (make-token))) => true

(defstruct token (cookie '("unique-string")) (counter (incf

*token-counter*)))

(eql (token-cookie *first-token*) (token-cookie (make-token))) => false

I.e., even though the second DEFSTRUCT is EQUAL to the first, the

structures are not EQL.

This is related to the compiler issue QUOTE-MAY-COPY, but is not the same

issue, since that proposal isn't proposing that QUOTE might copy its value

*every time* it is executed.


[Starting Points][Contents][Index][Symbols][Glossary][Issues]
Copyright 1996, The Harlequin Group Limited. All Rights Reserved.