Recursion Can';在达到基本情况后,我无法从Prolog中的递归返回结果

Recursion Can';在达到基本情况后,我无法从Prolog中的递归返回结果,recursion,prolog,reporting,read-eval-print-loop,Recursion,Prolog,Reporting,Read Eval Print Loop,我试图了解Prolog递归是如何工作的。由于某种原因,在到达基本情况后,它会将所有结果放回原处。代码如下: makeMove([0 | Tail], List). makeMove([Head | Tail], List) :- Head1 is Head - 1, makeMove([Head1 | Tail], [[Head1 | Tail] | List]). move(InputList, Output) :- makeMove(InputList, Outpu

我试图了解Prolog递归是如何工作的。由于某种原因,在到达基本情况后,它会将所有结果放回原处。代码如下:

makeMove([0 | Tail], List).
makeMove([Head | Tail], List) :-
    Head1 is Head - 1,
    makeMove([Head1 | Tail], [[Head1 | Tail] | List]).

move(InputList, Output) :-
    makeMove(InputList, Output).
我在这里要做的是生成列表列表,它可以通过从输入列表的第一个元素减去1直到它为0来形成。 以下是堆栈跟踪:

[trace]  ?- 
|    move([3,4,5], X).
   Call: (8) move([3, 4, 5], _23538) ? creep
   Call: (9) makeMove([3, 4, 5], _23538) ? creep
   Call: (10) _23792 is 3+ -1 ? creep
   Exit: (10) 2 is 3+ -1 ? creep
   Call: (10) makeMove([2, 4, 5], [[2, 4, 5]|_23538]) ? creep
   Call: (11) _23816 is 2+ -1 ? creep
   Exit: (11) 1 is 2+ -1 ? creep
   Call: (11) makeMove([1, 4, 5], [[1, 4, 5], [2, 4, 5]|_23538]) ? creep
   Call: (12) _23840 is 1+ -1 ? creep
   Exit: (12) 0 is 1+ -1 ? creep
   Call: (12) makeMove([0, 4, 5], [[0, 4, 5], [1, 4, 5], [2, 4, 5]|_23538]) ? creep
   Exit: (12) makeMove([0, 4, 5], [[0, 4, 5], [1, 4, 5], [2, 4, 5]|_23538]) ? creep
   Exit: (11) makeMove([1, 4, 5], [[1, 4, 5], [2, 4, 5]|_23538]) ? creep
   Exit: (10) makeMove([2, 4, 5], [[2, 4, 5]|_23538]) ? creep
   Exit: (9) makeMove([3, 4, 5], _23538) ? creep
   Exit: (8) move([3, 4, 5], _23538) ? creep
true 

最内层调用中的输出值是前一个调用的值,上面放了一些东西,但是Prolog变量是不可变的。你所拥有的是一种中间状态。要从上一个结果中获得它,需要第三个参数:

makeMove([0 | Tail], Result, Result).

makeMove([Head | Tail], List, Result) :-
    Head1 is Head - 1,
    makeMove([Head1 | Tail], [[Head1 | Tail] | List], Result).

move(InputList, Output) :-
    makeMove(InputList, [], Output).

这不是您唯一的问题,但这应该会让您渡过难关。

如果成功地证明了所给出的查询,Prolog会向我们报告查询中存在的所有自由变量。例如,证明

?- move([3,4,5], X).
如果成功(并且将会成功),将向我们报告
X
现在持有的值

这将是。。。仍然是
X
,因为你什么都不做

您的证明在执行过程中会在
X
的顶部添加内容,但当到达最终案例时,所有这些内容都不会绑定到从顶部查询可以到达的任何内容
X
用作输入,任何地方都没有记录输出

为了得到这个“输出”,通常使用Daniel答案中给出的解决方案——另一个,第三个参数被提供给查询,一直不变地传递,并且仅在构建完整解决方案时,绑定到最深的子句


此时,Prolog将暂停,并向我们报告我们在查询中提供的所有自由变量。其中之一就是刚刚设置为引用刚刚构建的完整解决方案的解决方案。

“将所有结果放回去”-这是Prolog专门设计的功能-它被称为“回溯”。@Enigmativity这不是这里实际发生的事情。这只是一个递归调用,没有用于绑定计算状态的基本大小写。@DanielLyons-是的,但它仍然在回溯。@谜性不是在构造第一个证明时,还没有回溯,那么。@WillNess:为什么这些标记?