There was an old person of Woking,
Whose mind was perverse and provoking;
He sat on a rail,
With his head in a pail,
That illusive old person of Woking.
If we focused on the first and last lines of this example individually we could suppose, of course, that they conformed to patterns such as
First line: There was a KIND.OF.PERSONof PLACE
Last line: That ADJECTIVE KIND.OF.PERSON of PLACE
We could handle them, in other words, just as we did the Lonely Hearts advertisements by viewing them as a series of slots (or categories) which must be filled differently on different occasions.
But the first and last lines of a limerick are obviously not independent in the way that two Lonely Hearts advertisements are. The category KIND.OF.PERSON in the limerick's last line cannot be replaced randomly by some word from a list. On the contrary, it has to be treated as a place-holder for the specific word or phrase which was chosen to fill the KIND.OF.PERSON slot when the first line was created. In programming terms, it must be treated as a variable which has previously been assigned some value.
It seems, then, that if we are to generate limericks using a production rule system, the action component of a rule must on different occasions do different things to create fillers for the category slots of the sentence structures. Sometimes it will no doubt be appropriate to provide words or phrases randomly pulled from a list (as in the case of ADJECTIVE in the last line of the example), but at other times it will be necessary to get hold of the value of a variable. It follows from this that the action component of the rules must explicitly mention the type of operation which generates the substitute.
You will recall the general condition-action pattern represented by all rules in our earlier production system was :
IF the working memory contains this constituent THEN replace the constituent in the working memory by a randomly chosen element from this substitution list
In these circumstances, it was possible to use a highly abbreviated structure to represent a rule. In the case of the action component, there was no need to refer either (a) to the action of substitution or (b) to the use of pickrandom for selecting the substitute from a list. The only way in which the action components of rules could differ was in the list from which the replacement was to be picked. As a result only the substitute list was identified.
What we need now will be more complicated. The condition-action pattern which new rules must express - still as succinctly as possible - is :
IF the working memory contains this constituent THEN replace the constituent in the working memory by whatever object is generated when the specified instruction is carried out
It requires, however, only a simple extension to the form of the action component of our rules and a straightforward modification to our production system interpreter - specifically the procedure do - to provide for this interpretation.
Suppose, for example, we will specify the use of pickrandom, when need be, in the following way in the action component of a rule:
[pickrandom [man woman girl]]
and suppose that in other circumstances we identify the appropriate action with:
Although such action-component structures are obviously more complicated (contain more information) than those of our previous rules, you can see that in fact they are nothing more than normal Logo instructions. taking advantage of the primitive run, we then simply adapt the procedure do so that it canrun them.
to do :cond :act (pr "firing :cond "\-\> :act ) make "wm replace :cond run :act :wm pr :wm pr [ ] end