Template Creation With Macros and Looping Tutorial
Introduction
In this tutorial you will learn how to create complex pattern/template groups using Macros and loops in MakeAiml. This tutorial depends on content from the following tutorials:
MakeAiml Macros
If you are familiar with the C programming language, you probably understand what a "macro" is, if you're not don't worry because the concept is very simple. A MakeAiml macro works exactly like C object-type macros do in that it is simply an identifier to let MakeAiml know to replace the macro with predefined text. Here is an example:
! Remember...comments begin with the ! character
! The macro on the next line defines the bot's name
$ my_name Larry
p what is your name
t My name is $$my_name.
There are two lines you need to look at above, line 3 (begins with the dollar sign $) and the line that starts the template (begins with t). Line 3 tells MakeAiml to remember a macro called my_name which contains the text Larry. In order to "use" this macro, all a programmer needs to do is insert the name of the macro somewhere into the line of MakeAiml code prefixed with two dollar signs $$. When MakeAiml reads the line:
t My name is $$my_name.
It will see:
t My name is Larry.
All spacing around the macro is preserved, so don't be afraid to allow the name of the macro to run together with the surrounding text...like so:
$ i_am_a robot
p you are weird
t Please don't hold my $$i_am_aness against me :-(
MakeAiml will see the template line as:
t Please don't hold my robotness against me :-(
It might take a little thinking to get the macro expanded correctly, but you will understand how powerful of a tool this can be in the next section of the tutorial.
MakeAiml Loops
What good would MakeAiml be if it didn't allow a programmer to repeat similar patterns and responses to cut down on work? This is why the concept of looping was introduced. Looping allows a programmer to take a single response and repeat it for many patterns. Greetings are the most obvious situation where repetition is useful. Since the loop is applied mainly to pattern tags, the loop is an extension of the pattern tag. Instead of typing p, type pf to instantiate what is called a Pattern-For loop. The syntax for a Pattern-For loop is pf followed by a list of words to iterate through. Each word is delimeted by a space, so for multiple word elements, surround the words in quotes and they will be treated as a single element in the list. To add a placeholder to the list, use a space surrounded by quotes " ". Take a look below:
pf hi hello "what is up" hola howdy "what is going on"
t Hi, it's very nice to meet you!
MakeAiml will look at the above code and see a list of patterns followed by a template to apply to them all...kind of like shorthand for:
p hi
t Hi, it's very nice to meet you!
p hello
t Hi, it's very nice to meet you!
p what is up
t Hi, it's very nice to meet you!
p hola
t Hi, it's very nice to meet you!
p howdy
t Hi, it's very nice to meet you!
p what is going on
t Hi, it's very nice to meet you!
Loops don't end there though, they can be made much more complex by creating multiple loops for a single template:
p i
pf really " "
pf like love
p being with
pf dogs cats animals
t Really? I enjoy being with animals, too!
What that code will do is create 12 patterns, each with the template: Really? I enjoy being with animals, too!. So, the AIML produced will look like:
<pattern> I REALLY LIKE BEING WITH DOGS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I LIKE BEING WITH DOGS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I REALLY LOVE BEING WITH DOGS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I LOVE BEING WITH DOGS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I REALLY LIKE BEING WITH CATS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I LIKE BEING WITH CATS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I REALLY LOVE BEING WITH CATS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I LOVE BEING WITH CATS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I REALLY LIKE BEING WITH ANIMALS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I LIKE BEING WITH ANIMALS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I REALLY LOVE BEING WITH ANIMALS </pattern>
<template> Really? I enjoy being with animals, too! </template>
<pattern> I LOVE BEING WITH ANIMALS </pattern>
<template> Really? I enjoy being with animals, too! </template>
Combining Loops and Macros
MakeAiml Pattern-For loops and macros work very well together and enable a programmer to create reusable, easily fixable, and easily debuggable code. One good method for combining the two can be seen below:
$ like_terms like love
p i
pf $$like_terms
p fish
t You like fish? I HATE fish!
p i
pf $$like_terms
p dogs
t I like dogs, too!
As you can see, a single macro was made to define general emotions and that one macro was reused for multiple Pattern-For loops. This makes the code easily expandable...if I want to add a new "like term" for the bot to watch for, all I need to do is place it at the end of the like_terms macro and it is automatically expanded by MakeAiml everywhere else in the file! If this new term were added into an AIML file, a programmer would likely spend a few minutes to a few hours copying and pasting old AIML tags and editing them to provide the new "like term". In addition to this expandability, typos are easily fixed by consolidating all the "like terms" into one macro. If I make a typo in the list of "like terms" I reduce the probability of copying and pasting that typo elsewhere in the code and only need to fix the typo in one location.
Loop Tricks
In the release of MakeAiml 2.05 I added a feature that allows a user to directly reference elements in a pattern-for loop. A reference looks like a macro and is handled the same way. References look like the following: $$[A][B], where A and B are integers used to index into the list of elements (starting from 0). Here's an example:
p i
pf " " really
p love
pf dogs cats fish animals
t You love $$[1][*]? I love all kinds of $$[1][3]!
There are two references in the template line, the second template is $$[1][3] and has values of A=1 and B=3. This reference will expand to become the fourth element of the second pattern-for loop. The numbering scheme starts from zero because arrays in most programming languages follow this numbering scheme, it may be confusing to begin with, but learning this indexing scheme will only help prepare you to use other programming languages. You can think of the indexes for the example above in terms of the following table:
$$[A][B] is:
B 0 1 2 3
A
0 " " really
1 dogs cats fish animals
There is a special value that can be used for element B and it is the asterisk (*) character. As each pattern-for element is looped through, the special index * will choose the current loop element that is being processed. The best way to learn how pattern-for elements are processed is to generate the following in MakeAiml and view the output XML in a text editor.
p a
pf b c d
p e
pf f g h
t Z
By generating the above in MakeAiml and paying attention to what values appear in which area of the pattern it will become clear the order in which each element was processed. This will provide insight into how to index elements in the pattern-for list.
About the Author
Grant Dryden works in the defense industry as a computer engineer. He writes software in C and C++ for embedded systems as well as firmware in VHDL. He has a Bachelor of Science in Computer Engineering and is currently working towards a a Master of Science in Information Security.

