I was playing with permutation
in a couple of programs and stumbled upon this little experiment:
Permutation method 1:
permute([], []).
Nice example. But I would rather use, it doesn't leave a choice point in permute([], []):
permute3([], []).
permute3([H|T], [P|P1]) :-
select(P, [H|T], L1),
permute3(L1, P1).
Its tail recursive and like 20% faster than permute2/2, but still not as fast as permute1/2.
?- time((permute2([1,2,3,4,5,6,7,8,9,0],_), fail; true)).
% 29,592,302 inferences, 1.653 CPU in 1.667 seconds (99% CPU, 17896885 Lips)
true.
?- time((permute3([1,2,3,4,5,6,7,8,9,0],_), fail; true)).
% 25,963,501 inferences, 1.470 CPU in 1.480 seconds (99% CPU, 17662390 Lips)
true.
But I am not sure whether the explanation by mat is correct. It could be also the case that permute1/2 does less often perform LCO than permute3/2 does.
Namely of n! results of the sub call permute1/2, only the last redo doesn't leave a choice point. On the other hand in permute3/2 every select/3 call has n results and doesn't
leave a choice point in the last redo. I did a little test, write a period for each LCO:
?- permute1([1,2,3],_), fail; nl.
...
?- permute3([1,2,3],_), fail; nl.
..........
LCO has not an extreme benefit in a fail loop. But the Prolog system doesn't know about it. So I guess thats where unnecessary time is spent, to a larger amount in permute3/2.