刚开始用 prolog 编程,我遇到了一些问题。我拥有的函数应该取一个值 X 并将其 N 次复制到 M 中。我的函数返回 N 个内存位置的列表。这是代码,有什么想法吗?
duple(N,_,M):- length(M,Q), N is Q.
duple(N,X,M):- append(X,M,Q), duple(N,X,Q).
刚开始用 prolog 编程,我遇到了一些问题。我拥有的函数应该取一个值 X 并将其 N 次复制到 M 中。我的函数返回 N 个内存位置的列表。这是代码,有什么想法吗?
duple(N,_,M):- length(M,Q), N is Q.
duple(N,X,M):- append(X,M,Q), duple(N,X,Q).
这些不是内存地址。这些是自由变量。您看到的是它们在您选择的 prolog 系统中的内部名称。然后,正如@chac 指出的那样(+1 顺便说一句),第三个子句没有任何意义!也许您可以尝试告诉我们您的意思,以便我们了解如何正确执行此操作。
我将为您提供两个谓词实现,以尝试向您展示正确的 Prolog 语法:
duple1(N, X, L) :-
length(L, N),
maplist(=(X), L).
在这里,在你的duple1/3
谓词中,我们告诉 prolog 结果列表的长度L
是N
,然后我们告诉它每个元素L
应该与X
谓词保持一致。
另一种做法是通过递归“手动”构建结果列表:
duple2(0, _X, []).
duple2(N, X, [X|L]) :-
N > 0,
NewN is N - 1,
duple1(NewN, X, L).
不过,请注意,因为我们使用>/2
,is
和-/2
,即算术,我们阻止 prolog 以多种方式使用这个谓词,例如:
?- duple1(X, Y, [xyz, xyz]).
X = 2,
Y = xyz.
这在我们的第一个谓词中之前有效!
希望这会有所帮助。
例如,我想您以这种方式调用谓词:
?- duple(3,xyz,L).
你得到
L = [_G289, _G292, _G295] ;
ERROR: Out of global stack
如果你试试
?- length(X,Y).
X = [],
Y = 0 ;
X = [_G299],
Y = 1 ;
X = [_G299, _G302],
Y = 2 ;
X = [_G299, _G302, _G305],
Y = 3 ;
X = [_G299, _G302, _G305, _G308],
Y = 4 .
...
你可以看到发生了什么:
您的查询将匹配指定的*M*
,显示 M 未实例化变量(内存位置)的列表,然后继续回溯并生成更长的列表,直到有堆栈空间。你的第二条规则永远不会触发(我不太明白它的目的)。
以这种方式编写生成器更容易:
duple(N,X,M) :- findall(X,between(1,N,_),M).
测试:
?- duple(3,xyz,L).
L = [xyz, xyz, xyz].