Вы можете превратить общий термин в список, используя =..
, например,
?- conj(conj(x,y),z) =.. List.
List = [conj, conj(x, y), z].
Делая это рекурсивно, вы можете сгладить полный термин.
Общий предикат, который изменяетсянекоторые узлы во входном члене будут выглядеть примерно так:
change_term(NodeChanger, Term1, Term3) :-
call(NodeChanger, Term1, Term2),
change_term(NodeChanger, Term2, Term3),
!.
change_term(NodeChanger, Term1, Term2) :-
Term1 =.. [Functor | SubTerms1],
change_termlist(NodeChanger, SubTerms1, SubTerms2),
Term2 =.. [Functor | SubTerms2].
change_termlist(_, [], []).
change_termlist(NodeChanger, [Term1 | Terms1], [Term2 | Terms2]) :-
change_term(NodeChanger, Term1, Term2),
change_termlist(NodeChanger, Terms1, Terms2).
Если вы сейчас определите:
conj_changer(conj(X, Y), (X, Y)).
, тогда вы можете определить предикат Reduce следующим образом:
reduce(Term1, Term2) :-
change_term(conj_changer, Term1, Term2).
Использование:
?- reduce(conj(conj(x,y),z), ReducedTerm).
ReducedTerm = ((x, y), z).
Вы должны быть осторожны, хотя, как вы определяете NodeChanger
, некоторые определения могут сделать цикл change_term/3
.Может быть, кто-то может улучшить это.