Filling list (as an array) : without cut, backtracking leads to infinite recursion after giving a correct production

112 views Asked by At

I need to initialize some lists with a finite number of elements, all the same.

fill( 0, [], _ ) :- !.
fill( Index, [Value|List], Value ) :-
    NextIndex is Index - 1,
    fill( NextIndex, List, Value ).

The cut is mandatory to avoid infinite recursion and a fail result.

I tried to modify the rule #2 but after giving the expected solution, goal fails :

fill( Index, [Value|List], Value ) :-
    Index > 0,
    NextIndex is Index - 1,
    fill( NextIndex, List, Value ).

How it works:

?- fill( 7, AllFalse, false ).
AllFalse = [false, false, false, false, false, false, false].

?-
2

There are 2 answers

7
rajashekar On
eq(X, Y) :- X = Y.
fill(N, Xs, V) :-
    length(Xs, N), maplist(eq(V), Xs).

While this has no external cuts, length/2 has them in generative mode.

You are destructuring a integer value, when checking it's value you always create a choicepoint. If there was a natural number mathematically implemented as follows then you can have a deterministic fill predicate.

nat(0).
nat(suc(X)) :- nat(X).

fill_nat(0, [], _).
fill_nat(suc(N), [V|Xs], V) :-
    fill_nat(N, Xs, V).

?- fill_nat(suc(suc(suc(0))), Xs, a).
Xs = [a, a, a].
7
MWB On

I believe this works correctly:

fill(0, [], _).
fill(N, [Val|Tail], Val) :- 
    N > 0,
    N2 is N-1,
    fill(N2, Tail, Val).

(This is equivalent to your second version, and without the cut)

?- fill(2, X, 33).
X = [33, 33] .

?-

but after giving the expected solution, goal fails

It gives you one solution, and if you want more solutions, then it says "there aren't any".

?- fill(2, X, 33).
X = [33, 33] ;
false.

?-