Search code examples
prologprolog-findall

Find all in prolog


I have some employees:

employee(2,2,'George','Johnson','12/16/1987').
employee(4,3,'Noah','Jones','6/9/1984').
employee(5,4,'Jack','Brown','2/16/1992').
employee(6,6,'Charlie','Davis','3/28/1997').
employee(7,1,'Leo','Miller','6/6/1997').
employee(8,6,'Jacob','Wilson','2/16/1997').

I want to print of all them. I do it so now:

run :- findall(Id, employee(Id, _, _, _, _), L), writeEmployees(L).

writeEmployees([]) :- !.
writeEmployees([Id|T]) :- employee(Id, PosId, FN, LN, Birth), 
   writeq(employee(Id, PosId, FN, LN, Birth)), nl, writeEmployees(T).

And it works, but it doesn't look ok, I mean, there're too many '_'s and I have to write 'Id, PosId, FN, LN, Birth' string. How can find employee directly in findall()?


Solution

  • Nothing really terribly wrong with what you have. Yes, you have four _ but that's fine if you do not care about any of those 4 arguments.

    However, you are skipping those arguments, then just retrieving them again later. If you want to avoid that, you could write your findall to capture everything you want, then write that list out with maplist.

    run :-
        findall(employee(Id, PosId, FN, LN, Birth),
                employee(Id, PosId, FN, LN, Birth), Employees),
        writeEmployees(Employees).
    
    writeEmployee(E) :- writeq(E), nl.
    writeEmployees(Es) :- maplist(writeEmployee, Es).
    

    Ultimately, though, it depends upon the broader application this might fit into. If you are managing employees in a broader case, it really is more efficient to manage them by Id and then retrieve the details only when you need them, as you currently have. You could, though, rewrite your current writeEmployees with maplist:

    writeEmployee(Id) :-
        employee(Id, PosId, FN, LN, Birth), 
        writeq(employee(Id, PosId, FN, LN, Birth)), nl.
    
    writeEmployees(EmployeeIds) :-
        maplist(writeEmployee, EmployeeIds).