Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.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
Prolog 错误:使用append/3超出全局堆栈_Prolog - Fatal编程技术网

Prolog 错误:使用append/3超出全局堆栈

Prolog 错误:使用append/3超出全局堆栈,prolog,Prolog,我有个问题。我想实现一个replace(E1,L1,E2,L2)谓词。 当L1和L2是相同的列表时,这一点成立,但在L1具有值E1的一个位置,L2具有E2。此外,只替换一个引用,它必须在任何模式下工作 例如: same_length([], []). same_length([_|A], [_|B]) :- same_length(A, B). replace(2[1,2,3,4],5,X)应该只有解决方案X=[1,5,3,4] 替换(2[1,2,3,2,1],5,X)应回溯解决方案X= [1

我有个问题。我想实现一个replace(E1,L1,E2,L2)谓词。 当L1和L2是相同的列表时,这一点成立,但在L1具有值E1的一个位置,L2具有E2。此外,只替换一个引用,它必须在任何模式下工作

例如:

same_length([], []).
same_length([_|A], [_|B]) :- same_length(A, B).
replace(2[1,2,3,4],5,X)
应该只有解决方案
X=[1,5,3,4]

替换(2[1,2,3,2,1],5,X)
应回溯解决方案
X=
[1,5,3,2,1]
X=[1,2,3,5,1]

替换(2,X,5,[1,5,3,5,1])
应回溯解决方案
X=
[1,2,3,5,1]
X=[1,5,3,2,1]

replace(X[a,b,c,d],Y[a,e,c,d])
应该只有解决方案
X=b,
Y=e

替换(X[1,2,3,2,1],Y[1,5,3,5,1])
应该没有解决方案(它 (如果失败)

我的实施:

 replace(E1, L1, E2, L2) :- 
    append(X, [E1|L_Tail], L1),
    append(X, [E2|L_Tail], L2).
这个代码很好。但是当
replace(2,X,5[1,5,3,5,1])
时,它应该返回
X=[1,2,3,5,1]
X=[1,5,3,2,1]
false
。它只返回前两个结果,
false
没有出现。程序最终出现
错误:已询问全局堆栈外
,它有两个答案:和。但是,我将回答“为什么这个解决方案不起作用以及如何修复它?”的问题

append/3
的第三个参数是变量或部分列表时,它会给出无限多个解决方案:

?- append(X, Y, [a|Z]).
X = [],
Y = [a|Z] ;
X = [a],
Y = Z ;
X = [a, _1860],
Z = [_1860|Y] ;
X = [a, _1860, _1872],
Z = [_1860, _1872|Y] ;
X = [a, _1860, _1872, _1884],
Z = [_1860, _1872, _1884|Y] . % and so on
因此,当第一个列表
L1
是一个部分列表时,对
append(X[E1 | Y],L1)
的调用将使“幻觉”列表越来越长。对
append/3
的第二次调用每次都会失败,Prolog将回溯,与第一次
append/3
一起生成更长的列表,依此类推。这就是为什么你会陷入无限循环,最终会耗尽内存(当列表变得太长时)

避免这种情况的一种廉价方法是,在将两个列表交给两个
append
s之前,确保两个列表都是长度相同的正确列表。例如:

same_length([], []).
same_length([_|A], [_|B]) :- same_length(A, B).
如果您使用的是SWI Prolog,则可以使用maplist和
yall
lambda:

maplist([_,_]>>true, L1, L2)
示例查询:

?- L2 = [1,5,3,5,1],
   maplist([_,_]>>true, L1, L2),
   append(X, [2|Y], L1),
   append(X, [5|Y], L2).
L2 = [1, 5, 3, 5, 1],
L1 = [1, 2, 3, 5, 1],
X = [1],
Y = [3, 5, 1] ;
L2 = [1, 5, 3, 5, 1],
L1 = [1, 5, 3, 2, 1],
X = [1, 5, 3],
Y = [1] ;
false.
已被询问,它有两个答案:和。但是,我将回答“为什么这个解决方案不起作用以及如何修复它?”的问题

append/3
的第三个参数是变量或部分列表时,它会给出无限多个解决方案:

?- append(X, Y, [a|Z]).
X = [],
Y = [a|Z] ;
X = [a],
Y = Z ;
X = [a, _1860],
Z = [_1860|Y] ;
X = [a, _1860, _1872],
Z = [_1860, _1872|Y] ;
X = [a, _1860, _1872, _1884],
Z = [_1860, _1872, _1884|Y] . % and so on
因此,当第一个列表
L1
是一个部分列表时,对
append(X[E1 | Y],L1)
的调用将使“幻觉”列表越来越长。对
append/3
的第二次调用每次都会失败,Prolog将回溯,与第一次
append/3
一起生成更长的列表,依此类推。这就是为什么你会陷入无限循环,最终会耗尽内存(当列表变得太长时)

避免这种情况的一种廉价方法是,在将两个列表交给两个
append
s之前,确保两个列表都是长度相同的正确列表。例如:

same_length([], []).
same_length([_|A], [_|B]) :- same_length(A, B).
如果您使用的是SWI Prolog,则可以使用maplist和
yall
lambda:

maplist([_,_]>>true, L1, L2)
示例查询:

?- L2 = [1,5,3,5,1],
   maplist([_,_]>>true, L1, L2),
   append(X, [2|Y], L1),
   append(X, [5|Y], L2).
L2 = [1, 5, 3, 5, 1],
L1 = [1, 2, 3, 5, 1],
X = [1],
Y = [3, 5, 1] ;
L2 = [1, 5, 3, 5, 1],
L1 = [1, 5, 3, 2, 1],
X = [1, 5, 3],
Y = [1] ;
false.

嗨,鲍里斯,它工作了。你的回答清晰而有条理。非常感谢你!嗨,鲍里斯,它工作了。你的回答清晰而有条理。非常感谢你!