比较列表和元素

时间:2017-09-17 11:29:17

标签: list prolog

我正在尝试比较和检索相应列表中的值。我的谓词是correspond_elements(V1, Xs, V2, Ys),我期望以下行为:

?- correspond_elements(a, [a,b,b,a], X, [1,2,3,4]).
X = 1;
X = 4.

在第一个列表V1中选中Xs的位置,Ys中的相应值将返回V2。到目前为止,我有这个:

% checks if the argument is a list
is_list([]).
is_list([_|T]) :-
    is_list(T).

% predicate
correspond_elements(V1, [X|Xs], V2, [Y|Ys]) :-
    is_list([X|Xs]),
    is_list([Y|Ys]),
    ( V1 == X ->
        V2 is Y
    ;
        correspond_elements(V1, Xs, V2, Ys)
    ).

仅获得第一个值:

?- correspond_elements(a, [a,b,b,a], X, [1,2,3,4]).
X = 1.

我知道一旦->子句成立,那么;之后的任何内容都不会被执行。很明显,我的代码只会获得它为X找到的第一个答案并停止,但我不确定如何在列表中继续递归并返回X的所有可能答案,即使在第一个答案已经找到。

1 个答案:

答案 0 :(得分:1)

正如您自己发现的那样,Prolog A -> B; C的if-then-else将检查条件A,如果true它将执行B(和不是C)。否则它将执行C(而不是B)。

如果CA,您希望执行true作为附加选项。这可以通过转换来完成:

foo(Some,Parameters) :-
    A
    -> B
    ; C.

成:

foo(Some,Parameters) :-
    A,
    B.
foo(Some,Parameters) :-
    C.

现在A可以作为B的守护者,但无论A成功还是失败,Prolog都会回溯并执行第二个foo/2子句。

如果我们删除is_list(..)谓词(在我看来有点冗长),我们可以生成谓词:

correspond_elements(X, [X|_], Y, [Y|_]).
correspond_elements(V1, [_|Xs], V2, [_|Ys]) :-
    correspond_elements(V1, Xs, V2, Ys).

我们不必在这里写条件V1 == X,因为我们在头部使用了统一。因为我们使用统一,所以它是V1 = X(一个等式符号),这意味着我们可以以更多方向的方式使用谓词。

查询第二个列表X中的元素:

?- correspond_elements(a, [a,b,b,a], X, [1,2,3,4]).
X = 1 ;
X = 4 ;
false.

查询两个列表中的所有元组AX(某种“zip”):

?- correspond_elements(A, [a,b,b,a], X, [1,2,3,4]).
A = a,
X = 1 ;
A = b,
X = 2 ;
A = b,
X = 3 ;
A = a,
X = 4 ;
false.

获取第一个列表中的元素:

?- correspond_elements(A, [a,b,b,a], 1, [1,2,3,4]).
A = a ;
false.

生成一个列表,列表中包含1

?- correspond_elements(A, [a,b,b,a], 1, L).
A = a,
L = [1|_G1285] ;
A = b,
L = [_G1284, 1|_G1288] ;
A = b,
L = [_G1284, _G1287, 1|_G1291] ;
A = a,
L = [_G1284, _G1287, _G1290, 1|_G1294] .