-2
eight(A,B):-
    eight(A,[],B).

eight([],X,X).
eight([A|B],C,X):-
    eight(B,[A|C],X).

询问

?- eight([a,b,c],X)
4

2 回答 2

1

The predicate eight that you wrote there reverses a list. You could have found this out by just trying with different lists, and seeing the outcome.

Down the rabbit hole

As I understand it, when you run eight([a,b,c],X). it finds the first/only predicate that matches eight/2, and unifies [a,b,c] with A, it keeps the variable X as a random variable, probably like _G1234. Next it calls the body of the predicate as:

eight([a,b,c], [], _G1234)

This checks for predicates it can unify its arguments with. Since it cannot unify the empty list with [a,b,c], it finds your second eight/3 predicate (eight([A|B],C,X)) and unifies [A|B] with [a|[b,c]], C with [], and passes the unknown variable along for the ride. It then calls the body of the predicate with the newly unified variables as:

eight([b,c], [a|[]], _G1234)

This checks again for predicates it can unify its arguments with. Again, the empty list cannot be unified with [b,c], so it finds your second eight/3 predicate again, and unifies [A|B] with [b|[c]], C with [a|[]], and passes that unknown variable along again. So it calls the body of this predicate as:

eight([c], [b|[a|[]]], _G1234)

Once again, it checks for predicates it can unify its arguments. And once again, the first predicate it can unify its arguments with is your second eight/3 predicate. So it unifies [A|B] with [c|[]], C with [b|[a|[]]] and passes that unknown along again. It calls the body now as:

eight([], [c|[b|[a|[]]]], _G1234)

Now when it checks for predicates it can unify with, it finds your first eight/3 predicate. It unifies the empty list with the empty list, X with [c|[b|[a|[]]]] and since there's only one X, as far as prolog is concerned, that is placed in both positions. So it ends up unifiying _G1234 with X which in this case is [c|[b|[a|[]]]]. We end up with something that looks like this:

eight([], [c|[b|[a|[]]]], [c|[b|[a|[]]]])

For the sake of simplicity, I'm going to simplify those lists to:

eight([], [c,b,a], [c,b,a])

Up predicate

This predicate has no body, so it is actually a fact. When a fact is unified, a valid solution is considered to have been found. So prolog starts backing up the chain until it reaches a decision point and displays a valid goal. It goes to the previous predicate as eight([c], [b,a], [c,b,a]), then up again as eight([b,c], [a], [c,b,a]), and again as eight([a,b,c], [], [c,b,a]), and finally to where it started in the clause of your eight/2 predicate as eight([a,b,c], [c,b,a]). So it has successfully unified your original X as you posed the query. And displays this to you as:

X = [c, b, a].

Being that you have no other decision points in your program, this is the only possible goal and control is returned to you for more queries.

In the future, if you want to know how a predicate works, turn on tracing, with swi-pl it's just the trace\0 predicate in the repl.

于 2013-05-11T22:21:32.790 回答
0

八(A,B):-八(A,[],B)。

八([],X,X)。

八([A|B],C,X):- 八(B,[A|C],X)。

小心 Prolog,它可能非常迂腐。

在让您的规则运行并运行您的查询之后。我有

八([a,b,c],x)。错误的。

于 2013-05-11T21:47:40.147 回答