The protocol to support this has the generic
functions EMPTYP, COPY,
CLIPPING-DATA,
and WRITABLE-CLIPPING-DATA. A more efficient drawing
function is used if the canvas's clipping path object is
EMPTYP, otherwise a slower function that
references CLIPPING-DATA is
used. WITH-GRAPHICS-STATE copies the clipping path with
COPY. Clipping path updates are written to the channel
returned by WRITABLE-CLIPPING-DATA.

I initially implemented this with three classes: CLIPPING-PATH,
EMPTY-CLIPPING-PATH,
and PROXY-CLIPPING-PATH. Here's how each class handles each
generic function:

EMPTY-CLIPPING-PATH

CLIPPING-PATH

PROXY-CLIPPING-PATH

EMPTYP

returns true

returns false

COPY

returns new EMPTY-CLIPPING-PATH

returns new
PROXY-CLIPPING-PATH,data slot is EQ to original

CLIPPING-DATA

no method

returns data slot value

WRITABLE-CLIPPING-DATA

change-class
to CLIPPING-PATH,initializes and returns data

returns data slot

change-class to CLIPPING-PATH,set data slot to copy-seq of
data slot

Then I
read Joe
Marshall's take on CHANGE-CLASS, which he calls —
with some caveats — horrendous. I don't want to use horrendous
things! So I implemented a different approach using only
one CLIPPING-PATH class:

add a COPY-ON-WRITE-P slot, initially false

a CLIPPING-PATH is EMPTYP if its data slot is unbound

COPY creates a new CLIPPING-PATH instance

if the original is EMPTYP, the new instance is also empty

otherwise it has the same (EQ) data as the original and a
copy-on-write flag of t.

CLIPPING-DATA returns the data slot

WRITABLE-CLIPPING-DATA checks if the clipping path is
empty:

if so, initializes and returns the data slot

otherwise, checks the copy-on-write flag:

if set, COPY-SEQs the data slot to itself, returns
the new data

otherwise it returns the data directly

The second approach seems ok to me (and I don't need a table to
explain it), but the first approach doesn't seem that
horrendous either. I didn't choose either technique for any special
reasons; they're just the first things that occurred to me.

What do you think? Are they about the same, or does one seem better
to you? Is there some other approach that would be even nicer? Let
me know.

Comments

Change Class

I recently had a similar dilemma parsing elf files.

Once I'd read all the sections of the file, I had an array of elf-section objects. Some of the sections have quite complicated semantics (eg relocation entries referencing symbols, symbol names, and some other code/data section) that couldn't really be accounted for while the sections were being read.

So I had two options - do a second pass over the sections, chaging them to a more specialised type than elf-section and have specific methods specialise on these for symbol lookup, or string lookup or whatever, or just have a number of different methods for retreiving different things specialised only to the base section type.

I went with this but I'm beginning to think it was the wrong decision in terms of long-term extensibility - it would be better to have the sections specialise themselves as there are many possible types: ultimately it's a means of reducing the combinatorial explosion becaue the section-entry acessors specialise only on what they have to and not on the general case and validate they are used correctly.