Другой подход. Если мы обеспечим себя этими предикатами более высокого порядка (каждый из которых полезен сам по себе),
select_with(_, _, [], []).
select_with(P, X, [Y|Ys], Ys) :- call(P, X, Y), !.
select_with(P, X, [Y|Ys], [Y|Ks]) :-
select_with(P, X, Ys, Ks).
foldl(_,[],Vn,Vn).
foldl(P,[X|Xs],V0,Vn) :-
call(P,X,V0,V1),
foldl_(P,Xs,V1,Vn).
тогда мы можем легко определить предикат, который будет истинным, если каждый член одного списка имеет одинаковый элемент в другом (используя ==/2
):
members_equal(A, B :-
foldl(select_with(==), A, B, []).
Этот предикат может быть специализирован для указанной цели, если мы убедимся, что входящие аргументы являются наборами переменных. Следующее - лучшее, что я смог придумать в этом направлении (но он съедает довольно много выводов):
is_varset([]).
is_varset([V|Vs]) :-
var(V),
maplist(\==(V), Vs),
is_varset(Vs).
(По крайней мере, в SWI Prolog использование sort/2
требует меньшего количества выводов, чем приведенное выше. Предположительно, это связано с тем, что сортировка выполняется на C. Кроме того, этот ответ все еще не приближается к элегантности подхода term_vars/2
- такова сила " смысловое восхождение »:)
person
Shon
schedule
25.02.2015
As
иBs
являются наборами свободных переменных. В моем ответе это гарантируется тем фактом, что они должны объединяться со вторым аргументомterm_variables/2
. - person Tudor Berariu   schedule 13.01.2015varset_seteq([A+B,a],[])
успешно работает во многих системах (по умолчанию). ... и объединяет аргументы. - person false   schedule 13.01.2015