Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prolog list insert at any position

New to Prolog, trying to write a predicate to give all the options that an element could be inserted in to a list at any position. Ex:

ins(a, [b,c], R). should give:

R = [a,b,c]
R = [b,a,c]
R = [b,c,a]

which it does, but then gives an error 'Out of Global stack'. Is there a way to make this more deterministic, give the results and be done? When it is run in reverse ie. ins(X, Y, [a,b,c]). It gives the expected results then says false indicating it has completed. Code:

app([],L,L).
app([H|T],L2,[H|L]) :- 
    app(T,L2,L).

ins(E, List, R) :-
    R = R1,
    app(R2, R3, R1),
    app([E], R4, R3),
    app(R2, R4, List).

Here is a link to run the code in an online compiler, SWISH (This also has an example of how I hope to use ins, but ins is the problem right now) Any Help would be appreciated!

like image 611
ABane Avatar asked Mar 07 '23 13:03

ABane


1 Answers

Did you notice how this went bad? First, Prolog was very nice and dandy and showed you how smart it is, and only later on it struck you: Buy. More. RAM. Now!

Wouldn't it be better if Prolog would be up front? Before showing any answer?

Well, you can force Prolog to do exactly this. Add a false at the end of your query like so:

?- ins(a, [b,c], R), false.
   resource_error(_). % ERROR: Out of global stack

And the same you can do with your remaining program: Simply add false such that the remaining program still loops or runs out of space. I came up with the following minimal failure-slice

app([],L,L) :- false.
app([H|T],L2,[H|L]) :-
    app(T,L2,L), false.

ins(E, List, R) :-
    R = R1,
    app(R2, R3, R1), false,
    app([E], R4, R3),
    app(R2, R4, List).

?- ins(a, [b,c], R), false.

That means that we have to modify something in the remaining visible part in order to get rid of that looping. In other words: As long as the visible part remains unmodified the error will persist — guaranteed!

For more on this technique to understand reasons for non-termination see failure-slice

The immediate fix would be to put the first app/3-goal last.


But there is something else: You used all kinds of variables that are difficult to fathom. Maybe stick to a more uniform scheme. Also, there is no need for appending [A] using app/3. You actually need only two app/3 goals.

like image 71
false Avatar answered Mar 31 '23 11:03

false