达到基本情况后无法从 Prolog 中的递归取回我的结果
Can't get my results back from recursion in Prolog after reaching base case
我正在尝试了解 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
最内层调用中Output的值是上一次调用的值加上一些东西,但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
作为输入,没有任何输出记录。
为了得到这个"output",通常采用丹尼尔的回答中给出的解决方案——另一个,第三个参数被提供给查询,一直不变地传递,并且只绑定在最深的子句当构建完整的解决方案时达到。
此时 Prolog 将暂停,并向我们报告我们在查询中提供的所有自由变量。其中之一将是刚刚设置为引用刚刚构建的完整解决方案的那个。
我正在尝试了解 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
最内层调用中Output的值是上一次调用的值加上一些东西,但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
作为输入,没有任何输出记录。
为了得到这个"output",通常采用丹尼尔的回答中给出的解决方案——另一个,第三个参数被提供给查询,一直不变地传递,并且只绑定在最深的子句当构建完整的解决方案时达到。
此时 Prolog 将暂停,并向我们报告我们在查询中提供的所有自由变量。其中之一将是刚刚设置为引用刚刚构建的完整解决方案的那个。