How can I replace a list in Prolog?

2019-09-05 07:30发布

I think it's very easy but I have no idea how to do that. I tried by attribuition, doing a list receive another list but don't work.

% H is the head of a coordenate and T the tail
% E is the element that will be placed in the position T
findLine([L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10],H,T,E,NewTray) :-
    H is 1,replace(L1,T,E,N),L1 = N;
    H is 2,replace(L2,T,E,N),L2 = N;
    ...
    H is 10,replace(L10,T,E,N),L10 = N;
    NewTray = [L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10].

I need that L1 be the N in this clause, I don't know how I can create a clause to modify the L1 inside the clause findLine. I thought in create clause to remove all elements and add the new ones one by one and call this at the attribuition place:

%L is the list, C a counter and N the new list
 rewrite(L,C,N) :- 
        Q is C,
        removeByIndex(Q,L,R),
        (Q \== 0 ->  rewrite(R,Q-1,N), !.

    removeByIndex(0,[_|T],T):- !.
    removeByIndex(I,[H|T],R):- X is I - 1, removeByIndex(X, T, Y), insert(H, Y, R).

But I continous with the same problem: the L1 are not modified :(

The idea is modify a line and replace on the tray.

PS: I'm sorry for my english, but the prolog topics are almost inative in the portuguese forum

标签: prolog
1条回答
不美不萌又怎样
2楼-- · 2019-09-05 08:13

I'm really unsure what you're trying to accomplish here, but I can point to a few things that strike me as symptoms of a misunderstanding.

First of all, you bind all the variables at the top and then you have essentially a bottom-out else case that looks like this:

NewTray = [L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10].

Well, you never assign to NewTray in any of your other cases, so NewTray is going to be uninstantiated most of the time. That does not seem likely to be what you intend to me.

Second, your cases have this structure:

H is 1,replace(L1,T,E,N),L1 = N;

First mistake here is that H is 1; is/2 is for evaluating arithmetic expressions; there's no difference between this and H = 1, and the equivalence of L1 and N means that this whole predicate could probably be written as:

findLine([L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10],1,T,E,_) :-
    replace(L1,T,E,L1).
findLine([L0,L1,L2,L3,L4,L5,L6,L7,L8,L9,L10],2,T,E,_) :-
    replace(L2,T,E,L2).
findLine(Line, _, _, Line).

I'm still confused by what you're trying to do, looking at that.

I suspect that you think L1 will have some value on the way into the relation and suddenly have a new, different value after the relation is used. That is emphatically not the case: variables in Prolog are bound exactly once; your assignment L1 = N or whatever is not going to cause L1 to "receive a new value" (because such a thing cannot happen in Prolog); instead it informs Prolog that L1 and N should be bound to the same value. What this means depends on circumstances; if they are both ground and not equal it will cause your predicate to fail, for instance, but if either of them is non-ground they will accept the value of the other.

I'm looking at what you're doing here and I can't help but think that you're essentially trying to do this:

replace([], _, _, []).
replace([H|T], 1, X, [X|T]).
replace([H|T], N, X, [H|Replaced]) :- 
  N > 1, succ(N0, N), replace(T, N0, X, Replaced).

Use it like this:

?- replace([1,2,3,4,5], 3, foo, Result).
Result = [1, 2, foo, 4, 5] 

I just can't for the life of me figure out what you're trying to do, and I don't know why you're bothering to bind all the variables in your list at once if you don't need them all at once.

Anyway, I hope this helps! Maybe if you show us more of what you're trying to do it will be more clear how we can help.

Edit: Elaboration on = and unification

Let's mess around with = and see what happens:

?- X = 3.
X = 3.

Probably nothing surprising about this.

?- 3 = X.
X = 3.

Unification is different from assignment. As you can see, it is not directional. This line would not have worked in any other language.

?- X = [1,Y,3].
X = [1, Y, 3].

Notice that Prolog has no issues with having variables remain free.

?- X = [1,Y,3], Y = 2.
X = [1, 2, 3],
Y = 2.

Now, because Y is the same in both positions, when you bound Y to 2, the middle value in X became 2 as well. There are data structures unique to Prolog that make use of this feature (difference lists).

?- X = [1,Y,3], Q = X, Q = [1,2,3].
X = Q, Q = [1, 2, 3],
Y = 2.

Now what makes this interesting is that we did not explicitly tell Prolog that Y is 2. Prolog inferred this by unification. You can see some more examples of that here:

?- X = [H|T], H = 3, T = [4,5].
X = [3, 4, 5],
H = 3,
T = [4, 5].

So here we said, X is composed of H and T and then told it what H and T are. But Prolog's unification doesn't care much about the order you do things:

?- X = [H|T], X = [1,2,3].
X = [1, 2, 3],
H = 1,
T = [2, 3].

Unification is transitive.

So what happens when Prolog cannot unify?

?- X = [1,Y,3], Q = X, Q = [1,2,3], Y = 4.
false.

Y has to be 2 for the first step, but it has to be 4 for the last step. Once a variable is bound, there's no changing it. This is just a more complex way of saying:

?- X = 2, X = 4.
false.

Prolog does not have "assignables", just variables.

查看更多
登录 后发表回答