Search code examples
listprolog

Permute into a list SWI-Prolog


How do you use the permute predicate to output into a list in SWI prolog?

The permutation/2 predicate only returns one result at a time.


Solution

  • If you want a list of all permutations, findall/3 is the way to go. If you want to print, you can use forall/2. Either case:

    case_a(In, L) :- findall(Perm, permutation(In, Perm), L).
    case_b(In) :- forall(permutation(In, Perm), writeln(Perm)).
    

    forall it's a general purpose builtin, implementing a failure driven loop, amazing for its' simplicity. I report the definition from SWI-Prolog library, I think it's interesting.

    %%  forall(+Condition, +Action)
    %
    %   True if Action if true for all variable bindings for which Condition
    %   if true.
    
    forall(Cond, Action) :-
        \+ (Cond, \+ Action).
    

    EDIT:

    As noted by false, if you have variables in your list, you should be aware of the different behaviour of findall/3 WRT bagof/3:

    ?- case_a([1,2,3],X).
    X = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]].
    
    ?- case_a([A,B,C],X).
    X = [[_G467, _G470, _G473], [_G455, _G458, _G461], [_G443, _G446, _G449], [_G431, _G434, _G437], [_G419, _G422, _G425], [_G407, _G410, _G413]].
    

    Note that each variable in in the second query output is different: that could be the request outcome, or not, depending on the problem at hand. Deciding the appropriate behaviour WRT the variable quantification is mandatory in the restricted class of problems where variables are data, i.e. metaprogramming, I think...