防止列表中变量的统一

时间:2018-01-21 21:12:04

标签: prolog

我正在尝试编写一个谓词,如果变量X和谓词f(X)都是输入列表L的元素,则返回1,如果至少其中一个,则返回0不见了。

这就是谓词应该做的事情:

?- f_in_list([X, f(X)], Val).
  should return Val = 1

?- f_in_list([X, f(Y), Z], Val).
  should return Val = 0, as X and Y are different variables.

我写了这个简单的代码:

f_in_list(L, 1) :-
    member(X, L),
    member(f(X), L),
    !.
f_in_list(_, 0).

我的问题是Prolog总是试图统一输入变量,因此它分别返回X = f(X)X = f(Y)。 我试图使用dif(X, f(X))来绕过这个问题,但即使这样也行不通。如果列表包含至少两个元素,则Val将始终为1.

有没有办法将变量转换为原子或字符串,所以Prolog无法统一变量?或者更好的是,有没有办法阻止同名变量的统一?

2 个答案:

答案 0 :(得分:3)

正如@lurker所提到的,您应该考虑使用==/2,因为只有当这两个术语在没有进一步统一的情况下已经相同时才会成功。

她是我的实施:

f_in_list(L, 1) :-
    member(X, L),
    member(f(Y), L),
    X == Y ,!.

f_in_list(_, 0).

示例:

?- f_in_list([X, f(X)], Val).
Val = 1.

?- f_in_list([X, f(Y), Z], Val).
Val = 0.

答案 1 :(得分:1)

这可以很好地利用==/2。此运算符不会统一,但会检查其参数是否相同。以下是==/2行为的一点点:

2 ?- X == X
|    .
true.

3 ?- X == Y.
false.

4 ?- X = Y, Z = Y, X == Z, write('yes'), nl.
yes
X = Y, Y = Z.

5 ?- X = Y, Z = W, X == Z.
false.

6 ?-

我们可以使用它来创建一个非统一的nu_member/2谓词:

nu_member(X, [Y|_]) :- X == Y.
nu_member(X, [_|T]) :- nu_member(X, T).

我们在f_in_list/2中使用它:

f_in_list(L, 1) :-
    member(X, L),
    nu_member(f(X), L),
    !.
f_in_list(_, 0).

结果是:

2 ?- f_in_list([X,f(X), Z], B).
B = 1.

3 ?- f_in_list([X,f(Y), Z], B).
B = 0.

4 ?- f_in_list([X,f(Y), f(Z)], B).
B = 0.

5 ?- f_in_list([X,f(Y), f(Z),Z], B).
B = 1.