library(samefunctor)
This library package is supplied to solve the following problem: often you
could
write code that works more than one way around except that this requires
calling functor/3
twice, and one of the calls must therefore precede the other. For
example,
reverse_terms(Term1, Term2) :- functor(Term1, F, N), % *** functor(Term2, F, N), % *** reverse_terms(N, 1, Term1, Term2). reverse_terms(0, _, _, _) :- !. reverse_terms(Z, A, Term1, Term2) :- arg(Z, Term1, Arg), arg(A, Term2, Arg), Y is Z-1, B is A+1, reverse_terms(Y, B, Term1, Term2).
As written, this can only be used to find Term2 given Term1.
If you swapped the two *** lines, you could find Term1 given
Term2, but then could not find Term2 given Term1. You can make a
bidirectional version of reverse_terms/2
by using the
predicate same_functor/3
in place of the *** lines:
reverse_terms(Term1, Term2) :- same_functor(Term1, Term2, N), % *** reverse_terms(N, 1, Term1, Term2).
library(samefunctor)
defines the following predicates:
same_functor(
?Term1,
?Term2,
?Symbol,
?Arity)
same_functor(T1, T2, F, N) if functor(T1, F, N) and functor(T2, F, N) are both true.
Either Term1, or Term2, or both Symbol and Arity
should be instantiated. This is the most general variant.
same_functor(
?Term1,
?Term2,
?Arity)
same_functor/3
is appropriate and the greater
generality of same_functor/4
is not needed.
same_functor(
?Term1,
?Term2)
Note that same_functor/4
has the same argument order as
functor/3
except that it has two "term" arguments at the front.
Whenever a predicate's arguments include a functor specification expressed as
two arguments, the function symbol and its arity,
those two arguments should always
be adjacent, with the function symbol first and the arity immediately
following. functor/3
and same_functor/4
obey this rule.