Recursive rules

Rules can be recursive, or self-referential. For example, we can define the ancestor relation using the following two rules:

@!{AncestorRule_Base}
?Person [ ancestor -> ?Ancestor ] :-
  ?Person [ parent -> ?Ancestor ].

@!{AncestorRule_Rec}
?Person [ ancestor -> ?Ancestor ] :-
  ?Person [ parent -> ?Parent ],
  ?Parent [ ancestor -> ?Ancestor ].

This rule pair demonstrates the common pattern of having one “base case” rule and one “recursive case” rule. This is analogous to recursive functions in functional programming, or induction proofs in mathematics. The first rule says that parents are ancestors. The second rule says that parents’ ancestors are ancestors.

As usual, when writing recursive rules, one has to take some care. Incorrect recursive rules can cause runaway reasoning that freezes the system.

For those who are familiar with Prolog, it is worth pointing out that while Flora supports cuts, one cannot rely on rule ordering in Flora. The “internal” order of the rules may be different from what you see in the file. If you feel the need for the usual Prolog pattern of using cuts and rule ordering, you can use Flora’s \if...\then...\else terms instead (discussed in section Control Flow Statements).