I have a function that outputs names that fit a specific constraint. This function is fine.
But I need to use that function to make another function that turns the outputs of the former function into a list. Being a complete beginner with Prolog, I have no clue how to do this.
My problem is that I don't know how to iterate over the outputs to append it to an accumulator. The function which outputs names does so, then I press ";" or SPACE and it outputs the next answer until it's out of answers. I figure this means I have to make multiple calls to the function then append it. But I don't know how many times I need to call it, since I can't iterate over it like a list with [Head|Tail].
Here's what I have so far(although it's probably wrong):
%p1(L,X) determines if chemicals in List X are in any of the products and stores those products in L
p1(L,X) :- p1_helper(L,X,[]).
p1_helper(L,X,Acc) :- has_chemicals(A,X),append(Acc,[A],K),L=K, p1_helper(L,X,K).
function that outputs names with query has_chemicals(X,[List of Chemicals]).:
%has_chemicals(X,Is) determines if the chemicals in List Is are in the chemical list of X.
has_chemicals(X,Is) :- chemicals(X,Y), hc(Y,Is).
%hc(X,Y) determines if elements of Y are in elements of X.
hc(Y,[]).
hc(Y,[C|D]) :- isin(C,Y), hc(Y,D).
Any help is appreciated.
findall(+Template, :Goal, -Bag)
: Creates a list of the instantiationsTemplate
gets successively on backtracking overGoal
and unifies the result withBag
.For example, how to collect all odd numbers from 1 to 15:
We can get all that odds one-by-one.
And we can collect them into a list:
I encourage you to visit this page especially if you use swi-prolog.
There are 4 predicates that do what you want :
findall/3
,findall/4
,bagof/3
andsetof/3
.To summarize, here is the test predicate I'll be working with :
First, the simplest, findall/3 and findall/4 :
They just return all the alternatives, with duplicates, without sorting, without binding the other free variables, as a normal list for
findall/3
and difference list forfindall/4
. bothfindall
s predicates succeed when the list is empty.Then, bagof. Basically,
bagof/3
works asfindall/3
but binds free variables. That means that the same query than above but withbagof/3
returns :By telling
bagof/3
not to bind all the free variables, you obtainfindall/3
:Still you have to note that
bagof/3
fails when the result is empty, wherefindall/3
doesn't.Finally,
setof/3
. It's basicallybagof/3
but with the results sorted and no duplicates :I think you are looking for a way to capture the output of isin/2. Then you can use the builtin with_output_to/2, and combine it with findall/3, as suggested by other answers.