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

Protocols for Smashing the State



Abstract: messages that cause side-effects should be clearly
distinguished from those that don't.  Polymorphism between the two is
more dangerous than convenient.


I agree with Heh that 

Set * MuSet::unionWith (Set *);

as a message that changes the receiver state into the old state
unioned with the argument, and then returns the receiver; is a bad
idea.  Especially when there is also the message

Set * ImmuSet::unionWith (Set *)

which doesn't change the receiver, but does return the union of the
receiver and the argument.  The clever trick here is that in both
cases the result is the union of the receiver and the argument.
However this trick only matters if someone can take advantage of
it--if someone can write code which works with a particular variable
bound to either one.  Such code would be too clever for me.  I suspect
that it was in recognition of this danger that you didn't provide this
message in the common superclass, preventing actual polymorphism
between the two.  But then why the attempt at symmetry?

In general, I'm quite paranoid about side effects.  I like it to be
generally clear when reading a piece of code where the side effects
may be occuring.  We don't have available to us the Scheme naming
convention of including a "!" in all functions that may side-effect,
but we do have an approximate substitute.  I like to declare all
messages and functions that may side effect as having a void return.
It is quite clear when a call appears in a not-evaluate-for-value
position that it's probably for-effect.

The major reason for violating this rule is normally to signal
failure, but that doesn't apply to us since we can BLAST.  There are
still many valid exceptions to this rule, but for these we should use
a name that clearly spells side-effect (like "store").

So how about

void MuSet::merge (Set *)

I don't at all like "merge".  What would be ideal would be a name that
had the same relation to "union" that "+=" had to "+".  It'd be great
if this turned into a general naming convention.  How about

void MuSet::unionInto (Set *)

with the "Into" suffix being the general convention?