Чтобы сформулировать проблему, для каждой головы foo
вы устанавливаете условие для каждого условия f1, f2
, т. Е.
foo :- f1.
foo :- f2.
, но вы хотите утверждать одно предложение длякаждая голова со всеми условиями соединена в одно тело:
foo :- f1, f2.
Ключевой шаг, который вам не хватает, - это преобразование набора характеристик для каждого животного в соединение, которое затем можно утверждать как тело.
Вот один из способов достижения этого результата, используя swi-prolog списки ассоциаций для группировки признаков:
:- use_module(library(assoc)).
assert_characteristics(Characteristics) :-
group_characteristics(Characteristics, GroupedCharacteristics),
maplist(assert_condition, GroupedCharacteristics).
% Conditions should be a conjunction, e.g., `(a, b, c)`
assert_condition(Head-Conditions) :-
maplist(make_check, Conditions, Checks),
list_to_conjunction(Checks, Conjunctions),
assertz(( Head :- Conjunctions )).
% ex. group_characteristics([foo-f1, foo-f2, bar-b1], [foo-[f1,f2], bar-[b1]]).
group_characteristics(AnimalCharacteristics, Grouped) :-
empty_assoc(Assoc),
group_characteristics(AnimalCharacteristics, Assoc, Grouped).
% helper for group_characteristics/2
group_characteristics([], Assoc, Grouped) :- assoc_to_list(Assoc, Grouped).
group_characteristics([Animal-Char|Rest], Assoc0, Grouped) :-
% Updating an existing animal with the new characteristic `Char`
( get_assoc(Animal, Assoc0, Chars, Assoc1, [Char|Chars]), !
% Otherwise, the key for `Animal` isn't present yet, so add it.
; put_assoc(Animal, Assoc0, [Char], Assoc1) ),
group_characteristics(Rest, Assoc1, Grouped).
% Convert a list of predictes into a conjunction of predicates
% ex. list_to_conjunction([a,b,c], (a, (b, (c, true)))).
list_to_conjunction([], true).
list_to_conjunction([P|Ps], (P, Conjuncts)) :- list_to_conjunction(Ps, Conjuncts).
% just a helper used in assert_condition/1
make_check(C, verificar(C)).
Пример использования:
?- assert_characteristics([foo-foo1, bar-bar1, foo-foo2]).
true.
?- listing(foo).
:- dynamic foo/0.
foo :-
verificar(foo2),
verificar(foo1),
true.
В моем примере необходимо добавить ряд улучшений и оптимизаций, например, сделать операцию группировки чистой или собрать характеристики в набор, чтобы предотвратить включение избыточных условий в тела.