Text generation Part Four

Prerequisites: You should have read Text Generation Part Three.

We are now ready to look at phrase factories and tackle recursion.

Phrase Factories

A phrase factory is a function that generates a new instance of ishml.Phrase. The ishml.Template object and its many prefixes are phrase factories. The suffixes of ishml.Phrase are phrase factories. However, not all methods of ishml.Phrase are phrase factory. Some merely return the existing phrase rather than a new instance. Take a look at listing 1.

Listing 1

Here an attempt was made to create new phrases from the animal phrase. It does not work because .populate() merely returns the original animal phrase with new data and does not generate a new phrase. As a result, both example1 and example2 refer to the same instance of ishml.Phrase that animal does. Instead of producing an amphibian and a rodent respectively, the examples both produce rodents because that was the last set of data populated.

Listing two below demonstrates how to properly create a phrase factory. Here example1 and example2 reference separate instances of ishml.Phrase and act independently of each other.

Listing 2

A phrase factory is made by simply creating a function that returns new instance of ishml.Phrase. Phrase factories are very useful for recursive phrases. They may also be used to extend ishml.Template and ishml.Phrase.

Recursion

In example1 of listing 3 below, we see a simple, non-recursive phrase for generating an unordered HTML list. This is fine as far is it goes, but it would be more useful if it automatically genereated sub-lists on demand to display deeply nested data. Recursion is used in example2 to provide a nested list that expands indefinitely to accomodate on the data provided.

Listing 3

A phrase factory function is assigned to the variable ul. The phrase generated by this function also includes a call to this phrase factory function, making it recursive. The second expression in the phrase checks to see if .list is present in the data collection. If it is, the data associated with .list is passed in the call to ul. This embeds a new instance of the phrase inside the phrase. The embedding of a new phrase will continue recursively as long as .list property is present in the phrase's data collection. If it is not present, the expression evaluates to an empty string. When writing recursive functions you must always ensure that there is always a way for the recursion to end, otherwise you will generate a stack overflow error.

List 4 shows another example of a recursive phrase.

Listing 4

The phrase factory, inside creates a phrase about opening a random number of containers, each inside the other and eventually revealing a treasure of some sort. This function is called recursively as long as the result of _.favor(...) is a container.

Modifying and Customizing

We have now covered the essentialss of working with ISHML phrases and templates. We have introduced most of built-in prefixes and suffixes, which should cover the majority of your text generation needs. Occasionally, you may want to use a custom function to modify the results of a phrase. Listing 5 introduces the .modify() suffix in example1. It takes a callback function as its argument. During evaluation, each is element in the phrase's result array is sent to the callback function. The callback funtion returns a text string that .modify() replaces in the results array.

Listing 5

While .modify() lets us apply modifications to phrases, the syntax is a bit bulky compared to custom prefixes and suffixes. Any function that returns a phrase, i.e., a phrase factory, can be defined as a custom prefix or suffix. In the listing above, the variable prefix is assigned to a phrase factory that does the same uppercase conversion seen in example1. The static method ishml.Template.define adds the phrase factory to the collection of available prefixes with the name shout. In example2 we see the newly defined .shout prefix in use.

We may also create simple suffixes that take no parameters by using the static method ishml.Phrase.define. In the list above we define a suffix called tron to append O-Tron to the ends of phrases. We use the .tron suffix in example3.

We could have just as easily made the .tron suffix a prefix; there really isn't much advantage of one over the other. However, as a general rule, if the intent is to modify the end of the phrase, it is better to create a suffix. It just makes the subsequent phrase definitions easier to read.

Next Steps

This has been a brief tour of text generation using the ISHML API. We did not cover all of the available prefixes and suffixes. See the API Reference for complete documentation.

I will happily answer any questions you may have about text generation on intfiction.org. Be sure to label your questions with the ISHML tag for promptest attention.