Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Binding prolog中的递归,绑定到变量_Binding_Recursion_Prolog - Fatal编程技术网

Binding prolog中的递归,绑定到变量

Binding prolog中的递归,绑定到变量,binding,recursion,prolog,Binding,Recursion,Prolog,我有一个递归子句,它接受2个列表,在每次递归调用中,我从列表中删除一个元素,并将这个新列表(删除元素)绑定到一个新变量 如果我写这个变量,这是正确的。但是,当我有一个模型时,它将回溯最后一个绑定(我需要的列表)到前一个绑定撤消的变量 我试图在这段代码中复制这种情况: test([],Test,Result). test([H|T],Test,Result):- member(H,Test), delete(Test,H,Test1), write(Test1),

我有一个递归子句,它接受2个列表,在每次递归调用中,我从列表中删除一个元素,并将这个新列表(删除元素)绑定到一个新变量

如果我写这个变量,这是正确的。但是,当我有一个模型时,它将回溯最后一个绑定(我需要的列表)到前一个绑定撤消的变量

我试图在这段代码中复制这种情况:

test([],Test,Result).
test([H|T],Test,Result):-
    member(H,Test),
    delete(Test,H,Test1),
    write(Test1),
    write('\n'),
    test(T,Test1,Test1).
test([H|T],Test,Test1):-
    test(T,Test,Test1). 

?- test([1,2,3],[5,2,4,6,1],R).
我确实理解,结果应该出现在条款的开头,如下所示:

test([H|T],Test,Test1)....
但是只有第一个递归调用会成功,这是我不想做的

有没有关于如何解决这个问题的线索

另外,我对prolog还比较陌生,只是在网上读了一些教程,做了一些简单的练习

filter([], []).

filter([Head|Tail], [Head|Result]) :-
    sometest(Head),
    filter(Tail, Result).

filter([Head|Tail], Result) :-
    \+ sometest(Head),
    filter(Tail, Result).
现在,要了解它是如何工作的,请在运行
filter/2
谓词之前尝试发出
trace/0
调用,该调用将详细说明执行过程(至少在swi pl中):

考虑这个谓词
sometest/1

sometest(N) :- N mod 2 =:= 0.
现在让我们触发跟踪模式:

?- trace.
true.
现在,让我们调用谓词:

[trace] ?- filter([1, 2, 3], R).
   Call: (6) filter([1, 2, 3], _G522) ? creep
   Call: (7) sometest(1) ? creep
   Call: (8) 1 mod 2=:=0 ? creep
   Fail: (8) 1 mod 2=:=0 ? creep
   Fail: (7) sometest(1) ? creep
   Redo: (6) filter([1, 2, 3], _G522) ? creep
   Call: (7) sometest(1) ? creep
   Call: (8) 1 mod 2=:=0 ? creep
   Fail: (8) 1 mod 2=:=0 ? creep
   Fail: (7) sometest(1) ? creep
   Call: (7) filter([2, 3], _G522) ? creep
   Call: (8) sometest(2) ? creep
   Call: (9) 2 mod 2=:=0 ? creep
   Exit: (9) 2 mod 2=:=0 ? creep
   Exit: (8) sometest(2) ? creep
   Call: (8) filter([3], _G597) ? creep
   Call: (9) sometest(3) ? creep
   Call: (10) 3 mod 2=:=0 ? creep
   Fail: (10) 3 mod 2=:=0 ? creep
   Fail: (9) sometest(3) ? creep
   Redo: (8) filter([3], _G597) ? creep
   Call: (9) sometest(3) ? creep
   Call: (10) 3 mod 2=:=0 ? creep
   Fail: (10) 3 mod 2=:=0 ? creep
   Fail: (9) sometest(3) ? creep
   Call: (9) filter([], _G597) ? creep
   Exit: (9) filter([], []) ? creep
   Exit: (8) filter([3], []) ? creep
   Exit: (7) filter([2, 3], [2]) ? creep
   Exit: (6) filter([1, 2, 3], [2]) ? creep
R = [2] ;
false.
如果您花时间理解prolog在这里的作用,基本上是:只要您没有发现谓词为true(基本情况,这里,
filter([],[])
),您就可以运行,然后根据到达该情况的路径向后构建列表。这里的意思是,如果某个测试为真,则在
Result
中添加
Head
,如果不是,则不添加

请注意,您需要像我一样在第二个子句中使用
\+条件
(这意味着无法证明该条件),或者在第一个子句中使用cut,如下所示,否则,在回溯过程中匹配的
头仍将通过第二个子句:

filter([], []).

filter([Head|Tail], [Head|Result]) :-
    sometest(Head),
    !,
    filter(Tail, Result).

filter([Head|Tail], Result) :-
    filter(Tail, Result).
现在,如果您使用swi pl,请注意,您可以直接使用
include/3
来实现您想要的功能(在其他实现中肯定会以这个或其他名称出现):


希望有帮助。

您能试着澄清一下您希望谓词做什么吗?至少对我来说,目前还不清楚。试着描述一下你希望
得到什么?-test([1,2,3],[5,2,4,6,1],R)
返回?这里的谓词真的是胡说八道,只是试图重新创建我的另一个(更大的)子句。我想要的是谓词在递归过程中删除列表中的一些元素。当我结束递归列表时,我得到的是作为变量绑定的I。我知道我做错了什么(每个递归都会得到另一个绑定),只是不知道如何解决这个问题。所以我给了谓词一个列表。它将遍历它并删除一些元素。我想要的是带有已删除元素的结束列表。
?- include(sometest, [1, 2, 3, 4, 5], R).
R = [2, 4].