prolog函数返回内存位置而不是值

prolog函数返回内存位置而不是值,prolog,prolog-toplevel,Prolog,Prolog Toplevel,刚开始用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). 例如,我想您可以这样调用谓词: duple(N,X,M) :- findall(X,between(1,N,_),M). ?-双工(3,xyz,L)。 你得到了什么 L = [_G28

刚开始用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).

例如,我想您可以这样调用谓词:

duple(N,X,M) :- findall(X,between(1,N,_),M).
?-双工(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(N,X,M) :- findall(X,between(1,N,_),M).
?-双工(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).
测试:


这些不是记忆地址。这些是自由变量。您所看到的是它们在您选择的prolog系统中的内部名称。然后,正如@chac指出的(+1 btw),第三条没有真正意义!也许你可以试着告诉我们你的意思,这样我们就可以了解如何正确地做

我将给出谓词的两个实现,以向您展示正确的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
-/2
,即算术,我们以几种方式阻止prolog使用此谓词,例如:

?- duple1(X, Y, [xyz, xyz]).
X = 2,
Y = xyz.
在我们的第一个谓词中,这在以前是有效的


希望这能有所帮助。

这些不是记忆地址。这些是自由变量。您所看到的是它们在您选择的prolog系统中的内部名称。然后,正如@chac指出的(+1 btw),第三条没有真正意义!也许你可以试着告诉我们你的意思,这样我们就可以了解如何正确地做

我将给出谓词的两个实现,以向您展示正确的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
-/2
,即算术,我们以几种方式阻止prolog使用此谓词,例如:

?- duple1(X, Y, [xyz, xyz]).
X = 2,
Y = xyz.
在我们的第一个谓词中,这在以前是有效的


希望这能有所帮助。

谢谢你的帮助,我还不擅长使用prolog。谢谢你的帮助,我还不擅长使用prolog。