Pragmas are annotations to rules and constraints that enable the compiler to generate more specific, more optimized code. A pragma can be a conjunction of the following terms:
already_in_heads
already_in_head(
Id)
passive(
Id)
For example, in the handler leq
, any pair of constraints, say
A leq B, B leq A
, that matches the head X leq Y , Y
leq X
of the antisymmetry
rule, will also match it when the
constraints are exchanged, B leq A, A leq B
. Therefore it is
enough if a currently active constraint enters this rule in the first
head only, the second head can be declared to be
passive. Similarly for the idempotence
rule. For this rule, it
is more efficient to declare the first head passive, so that the
currently active constraint will be removed when the rule fires (instead
of removing the older constraint and redoing all the propagation with
the currently active constraint). Note that the compiler itself
detects the symmetry of the two head constraints in the
simplification rule antisymmetry
, thus it is automatically
declared passive and the compiler outputs CHR eliminated
code for head 2 in antisymmetry
.
antisymmetry X leq Y , Y leq X # Id <=> X=Y pragma passive(Id). idempotence X leq Y # Id \ X leq Y <=> true pragma passive(Id). transitivity X leq Y # Id , Y leq Z ==> X leq Z pragma passive(Id).
Declaring the first head of rule transitivity
passive changes the
behavior of the handler. It will propagate less depending on the order in
which the constraints arrive:
| ?- X leq Y, Y leq Z. X leq Y, Y leq Z, X leq Z | ?- Y leq Z, X leq Y. Y leq Z, X leq Y | ?- Y leq Z, X leq Y, Z leq X. Y = X, Z = X
The last query shows that the handler is still complete in the sense that all circular chains of leq-relations are collapsed into equalities.