Search code examples
prologprolog-findall

Prolog multiple unifications to one variable


I need to unify all terms in database to one variable.

For given code:

man('a').
man('b').

main :-
        prompt(_, ''),
        man(X),
        write(X),
        nl,
        halt.

I get output:

a

I need to get something like:

['a','b']

Is it possible? I know about retract/1, which deletes the term from database, I could iterate trough all theese facts and retract them from database one by one, but that seems to be like shoting in the leg. Any given advice is apreciated.


Solution

  • If you have a collection of facts such as:

    man(a).
    man(b).
    

    As was stated in the comments, you can find all the solutions with findall:

    | ?- findall(X, man(X), Solutions).
    Solutions = [a, b]
    

    You can also modify your original program to use a failure-driven loop. fail in Prolog does just that: it fails, and so it causes Prolog to backtrack. Once man(X) fails to find more solutions, then the first clause of main will finally fail Prolog to the second clause which will simply succeed with no further action:

    main :-
        man(X),
        write(X),
        nl,
        fail.
    main.
    

    Now if you query main you get:

    | ?- main.
    a
    b
    
    yes
    | ?-
    

    In the context of a broader program, findall/3 may be preferred since it captures the solutions for you, whereas the above merely "prints" them out without collecting them. Although, there are times when that's all that is desired.