我必须编写一个程序来获取列表中的列表,并且应该反转每一个列表,然后返回结果。像这样:
doStuff([[1,2], [3,4], [5,6], [7,8]], R).
R = [[1,2], [4,3], [5,6], [8,7]]
这是我到目前为止所做的:
doStuff([],_).
doStuff([X,S|T],R):- reverse(S,Rev), add(X,Rev,R), doStuff(T,R).
doStuff([X|[]], R):- add(X,R,R).
reverse([X|Y],Z,W) :- reverse(Y,[X|Z],W).
reverse([],X,X).
add(X,[],X).
add(X,L,[X,L]).
我的问题是,在第二次迭代中,add函数失败。 我还担心当原始列表最后只包含一个列表时会发生什么。
答案 0 :(得分:0)
因为你说第二次迭代后add / 3失败了我假设你使用了trace / 0
无论如何,这是:
[trace] ?- doStuff([[1,2], [3,4], [5,6], [7,8]], R).
Call: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
Call: (7) lists:reverse([3, 4], _G496) ? creep
Exit: (7) lists:reverse([3, 4], [4, 3]) ? creep
Call: (7) add([1, 2], [4, 3], _G405) ? creep
Exit: (7) add([1, 2], [4, 3], [[1, 2], [4, 3]]) ? creep
Call: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
Call: (8) lists:reverse([7, 8], _G514) ? creep
Exit: (8) lists:reverse([7, 8], [8, 7]) ? creep
Call: (8) add([5, 6], [8, 7], [[1, 2], [4, 3]]) ? creep
Fail: (8) add([5, 6], [8, 7], [[1, 2], [4, 3]]) ? creep
Redo: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
Fail: (7) doStuff([[5, 6], [7, 8]], [[1, 2], [4, 3]]) ? creep
Redo: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
Fail: (6) doStuff([[1, 2], [3, 4], [5, 6], [7, 8]], _G405) ? creep
false.
那为什么会失败?这是因为prolog的主要特征之一 基本上,prolog中的变量,一旦它取值,它就永远不会改变 如果你到目前为止使用命令式语言,这听起来有点奇怪,但考虑到数学中完全相同的事情 例如,请考虑以下等式:
x+3=4
4-x=5
从第一次开始我们得到x = 1
从第二个我们得到x = -1
因为x不能是1和-1,我们说没有x来满足上面的等式;
不是x是-1,因为那是第二个(和最后一个)等式的值
在你的程序中发生了同样的事情:
doStuff([X,S|T],R):- reverse(S,Rev), add(X,Rev,R), doStuff(T,R).
所以第一次给R赋值,doStuff / 2用R的值调用。
显然,这不是正确的值,因此doStuff / 2失败
所以你怎么解决这个问题?看看你写[X,S | T]的方式来区分你想要处理的前两个元素。你只需对结果做同样的事情:
写它像[XResult,SResult | Rest]
当然,XResult将只是X而SResult将与S(Rev)相反
休息将是你从doStuff / 2的递归调用得到的东西
最后但并非最不重要的是,您应该检查最后调用的子句。
的内容