Counting the elements of a dynamic list and "evaluating" the solution (Prolog)

1.3k views Asked by At

The predicate, which I've created does not work correctly. The predicate should count the items of all the facts in the database and "evaluate" them. (I'll explain later what I mean by "evaluation")

E.g. the facts are:

:- dynamic listitem /1.
listitem(number).
listitem(letter).
listitem(word).
listitem(sentence).

The first predicate, I've created, collects all the facts into one list:

members(W) :- bagof(X,listitem(X),W).

Now I want to count the items in the list. So I created a general predicate for counting:

count([],0).
count([_|L],N) :- count(L,N1), N is N1+1.

My next predicated does not work properly. This predicate has to count all the items of the facts above.

count_members(U) :- one_list([bagof(X,listitem(X),_W)],U).

The problem is, that the database should be dynamic, so that I can add and remove other items. This means, that i cannot ask

?- count([number,letter,word,sentence],N) 

as the facts might have changed.

And the last step, that does not work at all, because my last predicate is wrong, should be the following: Writing "all_members(X)" prolog should return an evaluation. E.g. prolog should return "X = four items" for the query "all_members(X)", if the number of items in the database is 4. I hope you've understood my problem. Again, the predicate that I'm searching is "all_members(X)". The other predicates I've created should help me creating the actual one.

I'll be very happy if you could help me finding the solution to my problem! (otherwise I won't be able to fall asleep tonight...) Thanks!!

EDIT:

Sorry, I forgot to write my definition for one_list. My thought was to make e.g. a list looking like this:

 [[number], [letter], [word]] 

to a list looking like this:

[number, letter, word, list]

one_list(X,[X]) :- \+ is_list(X).
one_list([],[]).
one_list([X|Xs],Zs) :- one_list(X,Y), one_list(Xs,Ys), append(Y,Ys,Zs).
1

There are 1 answers

0
AudioBubble On

There seems to be some confusion in your question.

To count number of facts/1 if your database (which works as expected even if there are no facts currently in the database, as long as facts is declared as dynamic):

?- findall(X, facts(X), Xs), length(Xs, L).

Note that you can't say length(findall(...), L) because Prolog has predicates, not functions (as pointed out by Will Ness in the comments to your question)!

Creating a list of lists is strange and unnecessary. I don't quite understand why you need it (please elaborate if I am missing something important).

Using flatten/2 is not a crime but it usually points to a poor design decision.