Let’s start by creating the class `Form`.
As we said earlier, it represents the piece of paper or canvas where we draw Distinctions.
A number of messages come to mind, such as `size` and `isEmpty`. But while the implementation of collection like behavior is quite straightforward, the question remains: what kind of collection does `Form` resemble the most? To answer that question, we need to examine its interaction with distinctions.
If we consider the circles on a piece of paper metaphor for distinctions, we could think of them in terms of these things that divide a space into two regions.
We could also see them as these Portals that have the capability of taking us from one space to another. As such, distinctions are the links connecting two different forms.
> Just like in Croquet.
Because of this, distinctions could be implemented as some sort of association. In particular, distinctions can be named, and hence they should also remember their name.
The first axiom of the laws of form says that calling a name twice is the same as calling a name once. Therefore, a natural first approach would be to model forms in terms of a set of named distinctions.
> Watch out for the desire to optimize prematurely at this point.
Now it is time to choose instance names for our objects. We will start with class `Form`. What could we ask `aForm` to obtain a collection of the distinctions it contains? Well, the message `distinctions` sounds quite straightforward, and as such we will use it.
The names for distinctions require much more care. Distinctions are drawn on a form, and this is their form — in other words, the form of a distinction is where it is drawn. Therefore, `form` should answer the form where the distinction lives. Since `form` is now taken, what other selector could we use to access the form inside the distinction?
In these situations, it is good to review the language that is used to talk about distinctions. Let’s see… “distinctions separate a space into two disjoint pieces”, “distinctions are the boundaries between such pieces”, “distinction is perfect continence”. It seems like there is a theme of enclosure, or even Containment. The selector `contents` suggests itself. However, it is not clear that it is a good choice. This is because the contents of a distinction can only be accessed by crossing the distinction. As such, `contents` is intention obscuring because it seems to indicate it is fine to know about the contents of a distinction without crossing it — `contents` does not have strong encapsulation connotations. But not all is lost since we did mention the act of crossing distinctions. Thus, we will choose the verb instead of the noun, and send the message `cross` instead. If we let it be an accessor, then we will have an intention revealing instance name too.
To summarize, we have the following classes and instance names so far.
Object Form (distinctions) Distinction (form cross name)
Now we should design how these objects interact together by means of messages. Clearly, distinctions need a form where to live. This indicates that instances of `Form` will be created first, and that forms will create instances of `Distinction`. What would be a good process for these distinctions to be created and crossed into? What would *we* do if we wanted to distinguish something in a form?
At this point, very interesting questions appear. For us, intention distinguishes between different values, and the way in which we care about the differences determines the kind of distinctions we draw. And we just take this for granted. To illustrate the point, every so often Andrés Valloud tries to look at something as a blob, without further interpretation.
> In my experience, it is almost impossible to do with letters.
The association between the glyph and its meaning happens too quickly for it to be stopped. Drawing distinctions is so automatic for us that it is almost invisible.
When we try to reproduce this act in Smalltalk, we run into further difficulty. For example, what if we told a form to distinguish something? Certainly, we would tell it what to distinguish by means of an argument to a message. But in Smalltalk everything is an object, and therefore distinguishing something in a form object requires that the very something we are trying to distinguish must exist beforehand, so we can pass it as an argument. What is going on?
The issues are that objects are distinctions that live in the image, and that the Smalltalk image is a form. In other words, form and distinction objects are redundant because they reproduce what Smalltalk provides for free. Then why should we try to copy what is already given? Because reflecting on these matters can be quite valuable. Redundancy can work on our favor here, as it will make explicit something we usually take for granted. And when this happens, we will be able to change what we take for granted and create new things.
So we have our form, and an already existing distinction (in some other unspecified form) that we want to distinguish in the new form. In Smalltalk, it would be natural to take the object and put it in the new form. This new distinction would then be identical to the original one, and thus we could think of this re-distinction as some sort of copy or act of reference. But then, as per Laws of Form, if we take a distinction existing in some form, and copy it into another form, then we can refer to the copy as the name for the original distinction. And this is where things become interesting.
> What is being copied is the pointer to the object header, but fortunately we do not have to deal with that.
Interesting indeed: you could think of the form in your mind being the unspecified form, and the Smalltalk image being the form in which you copy distinctions already present in the unspecified form — oh.
First of all, since the copy is a name, and because we are in the Smalltalk image the copy is identical to the original, then each object we distinguish in the new form is both the object and its own name. In this way, Smalltalk objects have this very peculiar dual property: they are their own name.
> And when you cannot name them, they are garbage.
But then, if we do not need to care about distinction names explicitly, we can simply distinguish objects in our new form and let them stand for their own names. Our original design for form, a set of named distinctions, now looks very promising. Therefore we implement the following message.
Distinction>>= aDistinction ^self name = aDistinction name
In this way, forms would be the equivalent of sets. Of course, if necessary, we could easily implement `IdentityForm` and `IdentityDistinction`, but we will leave those for when we actually need them.
So all this is great, but. . . hey, aren’t we forgetting something? Well, yes we implemented = but we did not implement `hash`!
> Baaad programmer! Slap! Slap!
Distinction>>hash ^self name hash
We should not forget to implement `hash` when we refine `=`, as failure to do so can lead to issues that are quite hard to debug.
> Baaad doggie! Don’t chew on the power co@Σ?# +$∼!&Γ:* — NO TERRIER
Back to forms and distinctions now. At last, we can start implementing the messages that will allow us to give Shape to our silly putty. Since we cannot do much with empty forms, let’s start with the message below.
> In case you are wondering, the DOS character set includes (among others) the greek letters shown above. In particular, the index of Σ is 228, and that of Γ is 226.
Form>>distinguish: aName ^(self distinctionNamed: aName) ifNil: [ | distinction | distinction := Dictinction named: aName. distinction form: self. self distinctions add: distinction. distinction ]
We can enforce the *only one distinction per name* restriction because the first axiom of *Laws of Form* says that invoking the same name twice is the same as invoking it once. In other words, we are not altering the meaning of the form structure by doing so. To that effect, pay close attention at how `ifNil:` is not being used as a control mechanism, but rather as a means of replacement. Indeed, `ifNil:` should be read as meaning `butIfNil:` instead.
So how is `distinctionNamed:` implemented?
Form>>distinctionNamed: aName ^self distinctions detect: [:any | any name = aName] ifNone: [nil]
You may be tempted to use a dictionary here, but keep that temptation at bay for now — the exercises have the details.
Once we have these messages, we should be able to cross into another form via a distinction. To do that, we simply implement the following message.
Form>>cross: aName ^(self distinguish: aName) cross
Note how this can create a distinction the first time, and reuse it thereafter. This is consistent with the *Laws of Form* axiom that says that using a name twice is the same as using it once. Also, note how the distinction answers its contents form when answering the message cross. This emphasizes how important proper names can be.
Finally, there should be a way to undistinguish something. And what would a good selector for that be? Certainly, `undistinguish:` seems a bit coarse. The selector `forget:` is also misleading. We need to undo a distinction, and that is not the same as forgetting it.
Perhaps we could find a selector by looking at the state of things before the distinction occurred. Before the distinction was drawn, there were no differences in value.
Hmmm… perhaps we are getting somewhere. Let’s continue finding alternate ways to say the same thing.
Both sides of the distinction had the same value to us. We could use them interchangeably. They were equivalent to us. We did not need to care about their differences.
Well, all of these are positive assertions and we do not seem to be making much headway. How about some negative ones?
> The technique is almost automatic, to the point of seeming to have very little merit. However, it relies heavily on how evolution has worked for so much time. If something does not quite work, find a peculiar characteristic of it and apply some change. In other words, purposefully introduce mutations in how the Traversal of the space is done, and evaluate the outcome. Do the Random Walk.
We were looking at things with a coarser resolution. Both sides fell in the same bucket. We would not care if we picked one or the other. We would confuse one for the other.
Hold it right there! That is it!
Form>>confuse: aName | existingDistinction | existingDistinction := self distinctionNamed: aName. existingDistinction isNil ifTrue: [^self]. self distinctions remove: existingDistinction
Now that we have our basic *Laws of Form* objects in place, let’s see how this relates to distinctions existing in the Smalltalk form — I mean image.
Section 5.3.1 of A Mentoring Course on Smalltalk, An Efficient Reference Finder