emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Changing a cl-defstruct definition in a published package


From: Basil L. Contovounesios
Subject: Re: Changing a cl-defstruct definition in a published package
Date: Fri, 13 Jul 2018 20:38:20 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

João Távora <address@hidden> writes:

> On Thu, Jul 12, 2018, 21:13 Clément Pit-Claudel <address@hidden> wrote:
>
>>  I maintain package A, which contains this:
>>
>>    (cl-defstruct aaa-info
>>      line message)
>>
>>    (provide 'aaa)
>>
>>  Someone else wrote a package B that contains this:
>>
>>    (require 'aaa)
>>
>>    (defun bbb-print-message (info)
>>      (message (aaa-info-message info)))
>>
>>    (provide 'bbb)
>>
>>  Users have installed both packages through package.el.  I update A
>>  by adding a new field to the definition of aaa-info, and push the
>>  update to ELPA or MELPA:
>>
>>    (cl-defstruct aaa-info
>>      line column message)
>>
>>  Users update using package.el, but this does not cause b to be
>>  recompiled.  From this point on, any subsequent call to
>>  bbb-print-message to bbb-print-message fails: for example,
>>  (bbb-print-message (make-aaa-info :line 1 :column 2 :message "XYZ"))
>>  prints this:
>>
>>    Debugger entered--Lisp error: (wrong-type-argument stringp 2)
>>      message(2)
>>      bbb-print-message(#s(aaa-info :line 1 :column 2 :message "XYZ"))
>>
>>  Similarly, if I update the constructor of aaa-info to give the new
>>  'column' field a default value, instances created by the
>>  previously-compiled B will still be missing the 'column' slot,
>>  leading to all sorts of errors.
>>
>>  What is the recommended way to change a cl-defstruct definition
>>  without running into these issues?
>
> There's no way to fix the problem now without breaking backward
> compatibility because by now B's use of your accessor has been
> compiled into something that probably looks like an aref into an
> array.  So if you change your object layout in A, you break a compiled
> B.
>
> The way to avoid this beforehand is not to expose the defstruct's
> accessors as a public interface.  You can't think of them as
> functions, because they have compiler macros associated.  The easiest
> "solution" now is to make proper functions for those accessors that
> are public, and then having B recompiled.  Also consider if you really
> need defstructs for their speed, because they're usually an array in
> disguise.  Perhaps a (slightly, in most cases) slower eieio class
> would do.

If cl-defstructs boil down to an array in disguise (I don't know because
I've never looked into them), would appending (as opposed to prepending
or inserting) new slots maintain backward compatibility?  E.g. going
from:

  (cl-defstruct aaa-info
    line message)

to:

  (cl-defstruct aaa-info
    line message column)

instead of:

  (cl-defstruct aaa-info
    line column message)

(despite my finding the latter aesthetically nicer, as it groups line
and column together).

-- 
Basil



reply via email to

[Prev in Thread] Current Thread [Next in Thread]