Пролог: как извлечь списки из сложного термина
Мне поручено расширить существующий код Пролога, и я столкнулся с проблемой со структурой сложного термина. Этот сложный термин передается в качестве параметра предикату Пролога, который я пишу. Проблема в том, что мне нужно извлечь два списка из этого сложного термина, а структура термина неизвестна в продвинутом или фиксированном.
В частности, допустим, у меня есть термин "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)).