Пролог: как извлечь списки из сложного термина

Мне поручено расширить существующий код Пролога, и я столкнулся с проблемой со структурой сложного термина. Этот сложный термин передается в качестве параметра предикату Пролога, который я пишу. Проблема в том, что мне нужно извлечь два списка из этого сложного термина, а структура термина неизвестна в продвинутом или фиксированном.

В частности, допустим, у меня есть термин "Param", подобный этому:

lam(_G23075,
   drs([_G23084], [eq(_G23084, person), ant(_G23084, mask, sg)])+_G23075*_G23084)

У термина drs выше есть два списка, которые я хотел бы извлечь.

Если бы у Парама был только термин drs, я мог бы сделать это:

drs(L1, L2) = Param.

И тогда L1 и L2 будут содержать списки. Как это может работать со сложной структурой терминов, приведенной выше?

Ура,

Мартин

2 ответа

Решение

Вы можете деконструировать термин, например, с =..:

Следующий предикат extract_drs(+Term,-L1,-L2) возвращает два встречающихся списка. Он может иметь несколько решений, если существует несколько совпадений терминов.

extract_drs(drs(L1,L2),R1,R2) :- !,R1=L1,R2=L2. % the cut avoids that L1 or L2 are inspected
extract_drs(Term,L1,L2) :-
  compound(Term),           % check if it is a compound term and not a number, variable, etc.
  Term =.. [_Functor|Args], % get the arguments of Term
  member(Arg,Args),         % choose one argument
  extract_drs(Arg,L1,L2).   % and try to extract there the drs term       

Я бы написал

extract_drs(Term,L1,L2) :-
  compound(Term), (Term = drs(L1,L2) ; arg(_,Term,Arg), extract_drs(Arg,L1,L2)).

отредактируйте, как отмечает danielp, это расширение SWI_prolog, которое позволяет использовать arg/3 с несвязанным первым аргументом. Затем следует заменить

extract_drs(Term,L1,L2) :-
  compound(Term), (Term = drs(L1,L2) ; Term =.. [_|Args], member(Arg,Args), extract_drs(Arg,L1,L2)).
Другие вопросы по тегам