Martin Wunderlich
Martin Wunderlich

Reputation: 1884

Prolog: how to extract lists from complex term

I am tasked with extending some existing Prolog code and I have run into an issue with the structure of a complex term. This complex term is passed as a parameter to a Prolog predicate that I am writing. Problem is that I need to extract two lists from this complex term and the structure of the term is not known in advanced or fixed.

Specifically, let's say I have a term "Param" like this:

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

The drs term above has the two lists that I would like to extract.

If Param had the drs term only, I could do this:

drs(L1, L2) = Param.

And then L1 and L2 would contain the lists. How could this work with the complex term structure given above?

Cheers,

Martin

Upvotes: 3

Views: 1072

Answers (2)

CapelliC
CapelliC

Reputation: 60004

I would write

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

edit as noted by danielp, it's a SWI_prolog extension that allows to use arg/3 with first argument unbound. Then should be replaced by

extract_drs(Term,L1,L2) :-
  compound(Term), (Term = drs(L1,L2) ; Term =.. [_|Args], member(Arg,Args), extract_drs(Arg,L1,L2)).

Upvotes: 1

danielp
danielp

Reputation: 1187

You can deconstruct the term e.g. with =..:

The following predicate extract_drs(+Term,-L1,-L2) returns the two occurring lists. It may have multiple solutions if there are multiple occurrences of matching terms.

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       

Upvotes: 3

Related Questions