prologprolog-findall

How do I write 'findall' in a Prolog code itself?


So, I am very new to Prolog and I have to write a short code about timetable. How can I add the findall function to a code itself?

happening(monday,chemistry).
happening(monday,english).
happening(tuesday,chemistry).
happening(wednesday,maths).
happening(friday,chemistry).
happening(friday,maths).

And now I want to write a command that shows how many times do I have chemistry in a week.

find_lessons(X) :-
findall(X,happening(X,chemistry), Bag).

Solution

  • I assume you want the result, so the Bag, so you should rewrite find_lessons(X) to find_lessons(Bag):

    find_lessons(Bag) :-
        findall(X, happening(X,chemistry), Bag).

    This will then give a list of days when there is a chemistry lesson, so:

    ?- find_lessons(Bag).
    Bag = [monday, tuesday, friday].
    

    to count the number of lessons, you can use length/2:

    ?- find_lessons(Bag), length(Bag, N).
    Bag = [monday, tuesday, friday],
    N = 3.
    

    But one can do this more efficient. Right now there is overhead in constructing the list, and counting the elements. We can make use of the aggregate library [swi-doc] and use the aggregate/3 predicate [swi-doc]:

    ?- aggregate(count, X^happening(X, chemistry), Total).
    Total = 3.
    

    so we can count the number of chemistry lessons with:

    :- use_module(library(aggregate))
    
    num_chem_lessons(N) :-
        aggregate(count, X^happening(X, chemistry), N).