

Use Cases for Change-Class in Common Lisp - jsnell
https://www.snellman.net/blog/archive/2015-07-27-use-cases-for-change-class-in-common-lisp/

======
ianbicking
I recall setting obj.__class__ in Python (kind of the same thing – though
without the notion of slots), but I can't recall why that was useful. Hot-
reloading is the one case I can think of (one of the things mentioned).

~~~
nostrademons
It's a good alternative to the State or Strategy patterns when you only need
one per object and virtually all methods are affected. Using the pattern,
you'd need to explicitly delegate all calls to the state/strategy object. When
you change the class, you're effectively using the type object as the
state/strategy object, which makes perfect sense because it already contains
all the methods.

------
kazinator
> _Why would you change the class of an object rather than create a new object
> as a replacement? Because there might be references to the object all over
> the place, and updating all of those references to point to the new object
> might be a lot of work or even impossible._

Logically speaking, updating all references to the new object would be
_equivalent to change-class_.

If you update _all_ references to an object to a new one, you _cannot tell_
that there is a different object. In fact there is nothing to tell; it isn't a
different object.

For instance if both X and Y in some expression (EQ X Y) previously point to
the old object, then after this global update, both X and Y point to the new
object. EQ returns T either way.

(Think about copying garbage collectors.)

~~~
jsnell
I think you might have misinterpreted that paragraph somehow? It's not saying
that updating all the reference to point to the old object would have the
wrong effect. It's saying that updating the references might not be feasible.
A garbage collector has more access than an application programmer...

There is an interesting exception to that in Smalltalk, where the become:
operation will replace all references to one object with references to
another.

~~~
kazinator
It says clearly "change the class _rather than_ X". So X is not the same
changing the class, right?

Traversing the heap and actually replacing references could actually be a good
trade-off. It means that class objects don't need to be implemented as handles
which point to the real implementation, just in case someone uses change-
class. It depends on how often change-class is done.

change-class could tie in to a generational garbage collector. If change-class
is done on a baby object, we know that the tenured objects do not point
backward to that object, so we don't have to traverse them. Only other baby
objects (and of course areas like stack frames and registers).

~~~
jsnell
Right. The two things are different despite having the same ultimate effect,
since (in the context of Common Lisp) one is a generic operation provided by
the language, while the other is application-specific with no language support
and would need a fragile bespoke implementation for every single use. If the
discussion was about Smalltalk that provides become: but not CHANGE-CLASS,
it'd be a different question.

------
joe_the_user
In object-oriented languages (like c++ or java), changing an object's class
usually involve "up-casting" or "down-casting". Such operations are pretty
much by definition violations of some earlier architectural plan - either the
plan of the program or the plan of some library you are using (the code in the
article is modifying a thing passed to it by a third party library it seems).
That doesn't say they are "wrong" since it may be more cost-effective to fix
things "on the fly" but it seems like they are generally an indication you are
entering the realm of "technical debt", stretching a plan beyond it's initial
intentions.

~~~
yoklov
I've seen code that wrote directly to the vtable pointer (in c++). The code
knew what it was doing was dangerous, but jeez. Always made me uncomfortable.

FWIW I usually just use an enum. Easy to change on the fly, easy on the cache,
easy to serialize, doesn't require indirection, ... Lots of benefits. Pisses
off switch-phobic programmers, though.

~~~
kazinator
Change class is simulated in C++ via the State Pattern and possibly others.
Any pimpl variant can achieve an effective change class by allowing an
object's internal representation to be mutated to a new representation.

I once made a list/binary search tree library called Austin, purely in C. This
library lets you dynamically change the type of an object from one kind of
binary search tree to another. For instance from Red-Black to AVL or Splay. Or
to a sorted linked list. There is a "vtable" in there which gets swizzled to
point to different operations. During the swizzling, there are special
operations which handle the needed reorganizations of the tree.

