0
votes

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
You are actually really damn close to your solution. Just two lines. how is one_list defined? i.e., what have you tried so far?Christian Fritz
@ChristianF I edited my question. kind of forgot to write the definition down^^jazzsuite
Why so complicated? You already have your list (members(X)), now all you need to do is to count it, no?Christian Fritz
count_members(U) :- members(W), count(W,U). That's how Prolog's predicates are composed.Will Ness
You don't need count/2. You can just use length/2 built in predicate for the length of a list.lurker

1 Answers

1
votes

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.