/ GENTLE PRIMER
/ Describing Computations
defined in a rule are local to that rule.
Here are the constraints that must hold for the data flow inside a rule:
Each variable appearing inside a rule must be defined exactly once (i.e. occur in a pattern). A variable that appears in an expression of a member of the rule body (i.e. that is used as part of an input parameter of that member) must be defined in the rule heading (i.e. inside an input parameter) or in a preceding member of the rule body (i.e. inside an output parameter of a preceding member).
These laws make it possible for the disastrous error of uninitialized variables to be totally excluded by compile-time analysis.
Assume that we want to express that two persons like each other if they prefer the same color. Then we can write
'rule' likes(A, B): favorite(A -> AsFavorite) favorite(B -> BsFavorite) eq(AsFavorite, BsFavorite)using a predefined predicate eq that succeeds if invoked with equal arguments and fails if invoked with unequal arguments.
The first and second members compute the favorite color for A and B. Now as the values of AsFavorite and BsFavorite are known, they can be used as input to eq.
The first two members always succeed. The third member succeeds if AsFavorite and BsFavorite are equal, and fails otherwise. If the third member succeeds, then the rule succeeds, otherwise the rule fails. Since this is the only rule, an invocation likes(X, Y) succeeds if X and Y prefer the same color.
The example also shows that a variable cannot be defined twice. Using a common variable (say X) instead of AsFavorite and BsFavorite to express that these values must be equal, would violate the constraint because X would occur in two patterns. Instead, the equality must be expressed explicitly using eq. (This is to catch typing errors and to rule out the misunderstanding that the second definition overwrites the old value.)