Prolog element is a list member check

2019-03-03 10:25发布

问题:

I have a little rule in prolog that has to check if an element is a member of a list and write it's position in the list,but it only works if the elemebt i'm looking for is in the 1 place.Need help please!

write_element(X,[X|_],1).
write_element(X,[_|Tail],N):-
N1 is N-1,
write_element(X,Tail,N1).

回答1:

How exactly is this thing supposed to be called? It seems like N is going to have to be instantiated by me, or N1 is N-1 won't work. But similarly, N must unify with 1 in your base case, so if X is present in the list, N must equal one. So I think you have some basic confusion there surrounding how this is to be called. If you want to use N as a counter you probably can't also use it as a variable. You should revisit your thinking on decrementing though, because I don't see any reason to expect it to be called with a large value suitable for decrementing, unless there's a length/2 elsewhere in your code which you haven't shared.

Your second problem is that this does not write anything anywhere, and since you didn't include the actual problem statement I'm going to have to guess that what you probably actually want to do is just return the position, like nth1/3. We could use nth1/3 to implement this if you just want to print out the location if the element is present:

write_element(X, L, N) :- nth1(N, L, X), write(N).

Odds are good this isn't what is intended. If you want to implement something like nth1/3 it's going to be a little more interesting, because we need to keep separate the counter we're returning from the counter we're using. So it will wind up looking something like this:

write_element(X,L,N) :- write_element_loop(X,L,1,N).

write_element_loop(X, [X|_] , N,  N).
write_element_loop(X, [_|Xs], N0, N) :-
    N1 is N0+1,
    write_element_loop(X, Xs, N1, N).

This is actually really close to your code, I've just made the distinction between the counter and the return value explicit. If you want to print the values instead of just unifying them, you could add that to the end of the first rule:

write_element_loop(X,[X|_],N,N) :- write(N), nl.

Hope this helps!



回答2:

Since you report it's working only for the first position, here is the simpler correction possible to your code to make it work in other cases:

write_element(X,[X|_],1).
write_element(X,[_|Tail],N):-
  write_element(X,Tail,N1),
  N is N1 + 1.

but the answer from Daniel (+1) is what you should study.