Prologue: how to extract lists from a complex term
I was tasked with extending the existing Prolog code, and I ran into a problem with the structure of a complex term. This tricky term is being passed as a parameter to a Prolog predicate I'm writing. The problem is that I need to extract two lists from this complex term and the structure of the term is unknown in expanded or fixed form.
Specifically, let's say I have the term "Param" like this:
lam(_G23075,
drs([_G23084], [eq(_G23084, person), ant(_G23084, mask, sg)])+_G23075*_G23084)
The drs term above has two lists that I would like to extract.
If the Param parameter only had a drs member, I could do this:
drs(L1, L2) = Param.
And then L1 and L2 will contain lists. How would this work with the complex terminology structure above?
Greetings,
Martin
source to share
You can deconstruct the term for example. with =..
:
The following predicate extract_drs(+Term,-L1,-L2)
returns two occurrences of lists. It can have multiple solutions if there are multiple occurrences of the same term.
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
source to share
I would write
extract_drs(Term,L1,L2) :-
compound(Term), (Term = drs(L1,L2) ; arg(_,Term,Arg), extract_drs(Arg,L1,L2)).
edit as pointed out by danielp is a SWI_prolog extension that allows arg / 3 with the first unbound argument. Then it should be replaced with
extract_drs(Term,L1,L2) :-
compound(Term), (Term = drs(L1,L2) ; Term =.. [_|Args], member(Arg,Args), extract_drs(Arg,L1,L2)).
source to share