Zilonis Tutorial 3

Matching

So far, the patterns used to match rules against facts have been very simple and rather restrictive. Each pattern has matched one specific fact. By using wildcards, it is possible to make rules match multiple facts, executing their actions repeatedly. For instance, the rule:

    (defrule animal
      (animal ?v)
      =>
      (printout t "Animal found"))

Produces the following results when run:

    $(run)
    Animal found
    Animal found
    Animal found
    Animal found
    $

Which shows that it has triggered four times, once for each fact matching the (animal ?v) pattern.

Variables in patterns

In the last section we ignored the value of the ?v. We can use the value of ?var each time the rule is fired. Try this example:

    (defrule listAnimals
    (animal ?name)
    =>
    (printout t ?name " found"))

This will produce the following results:

    $(run)
    turtle found
    duck found
    cat found
    dog found
    $

The rule has matched four facts, and each time the variable ?name has taken the value of the symbol it represents in the pattern, so that in the action part of the rule it can be printed. The real power of this feature is apparent when two or more patterns are used, as in the next example:

    (defrule mammal
      (animal ?name)
      (warmBlooded ?name)
      (not (laysEggs ?name))
      =>
      (assert (mammal ?name))
      (printout t ?name " is a mammal"))

You may notice the not function sneaked in there. The purpose of this should be self-evident. This rule gives the results

    $(run)
    cat is a mammal
    dog is a mammal
    $

When you are satisfied that you understand how this works, try the next step:

    (defrule mammal2
      (mammal ?name)
      (childOf ?name ?young)
      =>
      (assert (mammal ?young))
      (printout t ?young " is a mammal"))

After you have run this rule, look at the fact list

    $(run)
    kitten is a mammal
    puppy is a mammal
    $gt;

Order and Logic

You've already seen that two or more patterns in a rule are automatically connected with a logical AND, which means that both must be true for the rule to fire. You've also seen the not function. But what if we wanted to test for an order relationship between 2 variables?. Zilonis offers the < > = and != operators. They can be used in the following way:

    (defrule older
      (person (name ?older) (age ?olderAge))
      (person (name ?younger) (age ?youngerAge))
      (test (> ?olderAge ?yongerAge))
      =>
      (assert (?older isOlder)))

Which means "if there is a person with an age, and that age is grater than the age of another person, then that person is older than someone". Notice the way the > comes before the two arguments, rather than between them. this is known as prefix notation, and all Zilonis operators work this way. For example, to express a sum of two numbers in most computer languages, you would use something like 5 + 7 (this is known as infix notation). In Zilonis, the expression would be written (+ 5 7). (the math operators are not currently supported)