0

I need to make a predicate called fAtomPairs so that given an atom (first argument), and a list of pairs (each pair is in turn a list of two atoms), unify a third parameter with the filtered list of pairs by selecting only those pairs that have as their first component the atom which is the first argument.

For example :

fAtomPairs(sA,[[basA,absAb],[ab,bbsA],[sA,abbsB],[bsA,sAsB],[sA,bb]],X)  

must result in

X = [[sA,abbsB],[sA,bb]]

How can I do this?, I'm currently working in SWISH

false
  • 10,264
  • 13
  • 101
  • 209

2 Answers2

5
:- use_module(library(reif)).   % SICStus|SWI
:- use_module(library(lambda)). % SICStus|SWI

fAtomPairs(Sel, DEs, Es) :-
   tfilter(\[A,_]^ ( Sel = A ), DEs, Es).
false
  • 10,264
  • 13
  • 101
  • 209
4

You can use a version of tfilter/3 and if_/3. I also changed the representation from lists of two elements to pairs.

fAtomPairs(sA,[basA-absAb,ab-bbsA,sA-abbsB,bsA-sAsB,sA-bb]).


tfilter(_CT_2,    [], []).
tfilter(CT_2, [E-Thing|Es], Fs0) :-
   if_(call(CT_2,E), Fs0 = [E-Thing|Fs], Fs0 = Fs ),
   tfilter(CT_2, Es, Fs).

=(X,X,true).
=(X,Y,false) :- dif(X,Y).


if_(If_1, Then_0, Else_0) :-
   call(If_1, T),
   (  T == true -> call(Then_0)
   ;  T == false -> call(Else_0)
   ;  nonvar(T) -> throw(error(type_error(boolean,T),_))
   ;  /* var(T) */ throw(error(instantiation_error,_))
   ).

Then query:

?-fAtomPairs(SA,Pairs),tfilter(=(SA),Pairs,Filtered).
Filtered = [sA-abbsB, sA-bb],
Pairs = [basA-absAb, ab-bbsA, sA-abbsB, bsA-sAsB, sA-bb],
SA = sA
false
user27815
  • 4,767
  • 14
  • 28