我正在尝试比较和检索相应列表中的值。我的谓词是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
的所有可能答案,即使在第一个答案已经找到。
答案 0 :(得分:1)
正如您自己发现的那样,Prolog A -> B; C
的if-then-else将检查条件A
,如果true
它将执行B
(和不是C
)。否则它将执行C
(而不是B
)。
如果C
为A
,您希望执行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.
查询两个列表中的所有元组A
和X
(某种“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] .