我需要找到列表S1和S2中存在的元素,我需要打印出这些元素(R)。
问题是,当我键入bendri([a,b,c,d],[d,b,e],R)
时,它会返回正确的结果[b,d]
,但它不会停止。如果按;符号,然后它继续检查并返回b
,之后 - d
。
为什么会这样?它应该只返回[b,d]
并结束它的工作。
bendri(S1,S2,R) :-
skaiciavimai(S1,S2,R).
skaiciavimai([],_,[]).
skaiciavimai([First|Tail], S2, [First|Rest]) :-
member(First, S2),
skaiciavimai(Tail, S2, Rest).
skaiciavimai([_|Tail], S2, Rest) :-
skaiciavimai(Tail, S2, Rest).
答案 0 :(得分:3)
你的问题是即使第二个子句成功,skaiciavimai([First|Tail], S2, Rest) :-
\+ (member(First, S2)),
skaiciavimai(Tail, S2, Rest).
的第三个子句也会成功回溯。如果第二个子句成功,我想你想跳过第三个句子。
为此,您可以在第三个子句中添加一个检查:
S2
如果在For Each element In Worksheets("SQLresults").Range("B")
中找到第一个列表的头部,则第三个子句失败。
答案 1 :(得分:2)
简单的故事:;
表示Prolog应该寻找替代方案,并且由于bendri(A,B,C)
被定义为“C
是 a 元素列表发生在A
和B
“(根据您的定义),它将打印所有可能的结果。您可以在下面的trace
上看到这一点(下面添加,因为跟踪相当长)。
问题是你在skaiciavimai/3
谓词中引入了一个决策点:确实第一个参数是一个至少包含一个元素的列表(格式为[_|_]
),Prolog环境可以选择第二个和第三个子句:在成功尝试skaiciavimai([First|Tail], S2, [First|Rest])
子句之后,它还可以选择下一个子句skaiciavimai([_|Tail], S2, Rest)
。由于没有谓词阻止该选择成功,因此它也会找到省略head元素的解决方案。您可以通过在最后一个子句中添加附加约束来解决此问题:
skaiciavimai([],_,[]).
skaiciavimai([First|Tail], S2, [First|Rest]) :-
member(First, S2),
skaiciavimai(Tail, S2, Rest).
skaiciavimai([First|Tail], S2, Rest) :-
\+ member(First,S2),
skaiciavimai(Tail, S2, Rest).
\+
意味着像逻辑而不是(虽然必须小心,因为逻辑编程中不是一个有问题的话题)。所以现在我们阻止Prolog成功选择第三个子句,因为First
是S2
的成员。使用此代码时,查询结果为:
?- bendri([a,b,c,d],[d,b,e],R).
R = [b, d] ;
false.
我们因此更改了skaiciavimai/3
的定义,现在它的内容如下所示:“C
是A
中B
中出现的所有元素的列表A
同样。“因为为了省略B
中的元素(第三个子句),它不应该是bendri/3
的成员。
在Prolog中,目标是使谓词多向。实际上,您希望能够以不同的方向调用谓词。可以实现bendri(A,B,[a,c])
,以便A = [a, c], B = [a, c] ;
也返回?- trace.
true.
[trace] ?- bendri([a,b,c,d],[d,b,e],R).
Call: (6) bendri([a, b, c, d], [d, b, e], _G360) ? creep
Call: (7) skaiciavimai([a, b, c, d], [d, b, e], _G360) ? creep
Call: (8) lists:member(a, [d, b, e]) ? creep
Fail: (8) lists:member(a, [d, b, e]) ? creep
Redo: (7) skaiciavimai([a, b, c, d], [d, b, e], _G360) ? creep
Call: (8) skaiciavimai([b, c, d], [d, b, e], _G360) ? creep
Call: (9) lists:member(b, [d, b, e]) ? creep
Exit: (9) lists:member(b, [d, b, e]) ? creep
Call: (9) skaiciavimai([c, d], [d, b, e], _G448) ? creep
Call: (10) lists:member(c, [d, b, e]) ? creep
Fail: (10) lists:member(c, [d, b, e]) ? creep
Redo: (9) skaiciavimai([c, d], [d, b, e], _G448) ? creep
Call: (10) skaiciavimai([d], [d, b, e], _G448) ? creep
Call: (11) lists:member(d, [d, b, e]) ? creep
Exit: (11) lists:member(d, [d, b, e]) ? creep
Call: (11) skaiciavimai([], [d, b, e], _G451) ? creep
Exit: (11) skaiciavimai([], [d, b, e], []) ? creep
Exit: (10) skaiciavimai([d], [d, b, e], [d]) ? creep
Exit: (9) skaiciavimai([c, d], [d, b, e], [d]) ? creep
Exit: (8) skaiciavimai([b, c, d], [d, b, e], [b, d]) ? creep
Exit: (7) skaiciavimai([a, b, c, d], [d, b, e], [b, d]) ? creep
Exit: (6) bendri([a, b, c, d], [d, b, e], [b, d]) ? creep
R = [b, d] ;
Redo: (11) lists:member(d, [d, b, e]) ? creep
Fail: (11) lists:member(d, [d, b, e]) ? creep
Redo: (10) skaiciavimai([d], [d, b, e], _G448) ? creep
Call: (11) skaiciavimai([], [d, b, e], _G448) ? creep
Exit: (11) skaiciavimai([], [d, b, e], []) ? creep
Exit: (10) skaiciavimai([d], [d, b, e], []) ? creep
Exit: (9) skaiciavimai([c, d], [d, b, e], []) ? creep
Exit: (8) skaiciavimai([b, c, d], [d, b, e], [b]) ? creep
Exit: (7) skaiciavimai([a, b, c, d], [d, b, e], [b]) ? creep
Exit: (6) bendri([a, b, c, d], [d, b, e], [b]) ? creep
R = [b] ;
等等(这种情况就是这种情况)。在设计谓词时,需要考虑谓词的多种用法。
skaiciavimai/3
答案 2 :(得分:2)
这个答案跟随@ gusbro的回答......为什么不保持逻辑纯洁?这很简单!
只需将第三个条款替换为:
skaiciavimai([First|Tail], S2, Rest) :- non_member(First, S2), skaiciavimai(Tail, S2, Rest).
并像这样定义non_member/2
:
non_member(X, Es) :-
maplist(dif(X), Es).
答案 3 :(得分:2)
这是前面提到的this logically-pure answer的后续行动。
:- use_module(library(lambda)). bendri(Es, Fs, Xs) :- % ^^ % || % |+----------------+\ % || || % vv vv tfilter(Fs+\E^memberd_t(E,Fs), Es, Xs). % ^^ % || % \+------------------ Fs has global scope
OP给出的示例查询:
?- bendri([a,b,c,d], [d,b,e], Xs).
Xs = [b,d].