Prolog 列表的最后一个成员是内存位置

Prolog 列表的最后一个成员是内存位置,prolog,Prolog,我不明白为什么这个谓词的最后一个位置是记忆位置 elimina_diretos(_,[],_). elimina_diretos(LA,[H|T],LP):- member(H,LA), elimina_diretos(LA,T,LP). elimina_diretos(LA,[H|T],[H|LP]):- elimina_diretos(LA,T,LP). 如果我打字 ?- elimina_diretos([tiago,andre],[pedro,tiago,roch

我不明白为什么这个谓词的最后一个位置是记忆位置

elimina_diretos(_,[],_).
elimina_diretos(LA,[H|T],LP):-
    member(H,LA),
    elimina_diretos(LA,T,LP).
elimina_diretos(LA,[H|T],[H|LP]):-
    elimina_diretos(LA,T,LP).
如果我打字

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
序言给了我:

L = [pedro, rocha|_G609] ;
我如何清洁该
\u G609

第一次更改:

elimina_diretos(_,[],[]).
请注意,您的代码必须具有确定性,否则回溯时会得到不需要的“解决方案”:

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro, rocha] ;
L = [pedro, rocha, andre] ;
...
然后是第二个变化(注意切口):

现在应该像你期望的那样工作了

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro, rocha] ;
false.
使用而不是
成员/2
,它的效率要高得多。

第一个更改:

elimina_diretos(_,[],[]).
请注意,您的代码必须具有确定性,否则回溯时会得到不需要的“解决方案”:

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro, rocha] ;
L = [pedro, rocha, andre] ;
...
然后是第二个变化(注意切口):

现在应该像你期望的那样工作了

?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro, rocha] ;
false.

使用而不是
member/2
,它的效率要高得多。

您的程序有几个问题。但首先,
\u G609
只是一个逻辑变量。您可以正确地假设这个数字与具体的内存位置有一定的关系。这种在顶层指示变量的特殊方式是SWI Prolog特有的。其他系统产生更全面的结果,例如GNU Prolog:

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro,rocha|_] ? ;
所以这个答案意味着
L
是一个部分列表,它以
pedro
rocha
开始。这是你想要的吗?也就是说

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,jose]).
true ?
这真的是你想要的吗?我想不是。但由于你没有说明这种关系应该描述什么,所以很难猜测

这不是你的程序的唯一问题。我们只看了第一个答案,但让我们看看后续的答案

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

L = [pedro,rocha|_] ? ;

L = [pedro,rocha,andre|_] ? 

yes
所以还有另一个答案

这里有一个非常通用的方法来快速发现这些错误。测试时,从最一般的查询开始,详细查看答案:

| ?- elimina_diretos(A, B, C).

B = [] ? ...
这意味着:
elimina_diretos/3
对所有
A
C
B=[]
都是正确的。我非常怀疑这是你想要描述的


((因为每个人都只是发布答案,所以我也必须这样做))


你的程序有几个问题。但首先,
\u G609
只是一个逻辑变量。您可以正确地假设这个数字与具体的内存位置有一定的关系。这种在顶层指示变量的特殊方式是SWI Prolog特有的。其他系统产生更全面的结果,例如GNU Prolog:

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).
L = [pedro,rocha|_] ? ;
所以这个答案意味着
L
是一个部分列表,它以
pedro
rocha
开始。这是你想要的吗?也就是说

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,jose]).
true ?
这真的是你想要的吗?我想不是。但由于你没有说明这种关系应该描述什么,所以很难猜测

这不是你的程序的唯一问题。我们只看了第一个答案,但让我们看看后续的答案

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

L = [pedro,rocha|_] ? ;

L = [pedro,rocha,andre|_] ? 

yes
所以还有另一个答案

这里有一个非常通用的方法来快速发现这些错误。测试时,从最一般的查询开始,详细查看答案:

| ?- elimina_diretos(A, B, C).

B = [] ? ...
这意味着:
elimina_diretos/3
对所有
A
C
B=[]
都是正确的。我非常怀疑这是你想要描述的


((因为每个人都只是发布答案,所以我也必须这样做))


只是为了在几个好答案中加入另一个选项

正如Capelical已经指出的,一个问题是基本情况不太正确:
elimina_diretos(u,[],u)。
这表示从空列表中删除任何一组项,我会得到一个匿名变量。在这种情况下,正确的“答案”应该是空列表:
elimina\u diretos(u,[],[])。

这是唯一的变化,然后您就可以很好地回答Capelic提到的多解决方案问题

修改条款的另一个选择如下:

elimina_diretos([], L, L).             % Remove nothing from L is L
elimina_diretos([H|T], L, LP):-
    (   delete(H, L, L1)             % L1 is L with all H's removed
    ->  elimina_diretos(T, L1, LP)
    ;   elimina_diretos(T, L, LP)    % There are no H's in L
    ).
产生:

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

L = [pedro,rocha] ? ;

no

| ?- elimina_diretos([a,b,c], [a,c,e,f], L).

L = [e,f]

yes

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,jose]).

no

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,andre]).

no

只是为了在几个好答案中加入另一个选项

正如Capelical已经指出的,一个问题是基本情况不太正确:
elimina_diretos(u,[],u)。
这表示从空列表中删除任何一组项,我会得到一个匿名变量。在这种情况下,正确的“答案”应该是空列表:
elimina\u diretos(u,[],[])。

这是唯一的变化,然后您就可以很好地回答Capelic提到的多解决方案问题

修改条款的另一个选择如下:

elimina_diretos([], L, L).             % Remove nothing from L is L
elimina_diretos([H|T], L, LP):-
    (   delete(H, L, L1)             % L1 is L with all H's removed
    ->  elimina_diretos(T, L1, LP)
    ;   elimina_diretos(T, L, LP)    % There are no H's in L
    ).
产生:

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],L).

L = [pedro,rocha] ? ;

no

| ?- elimina_diretos([a,b,c], [a,c,e,f], L).

L = [e,f]

yes

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,jose]).

no

| ?- elimina_diretos([tiago,andre],[pedro,tiago,rocha,andre],[pedro,rocha,andre]).

no

@错:我觉得你的评论有误导性。你真的希望一个新手能够理解抽象Prolog模型中令人不快的问题吗?你是在向一个新手建议一个高度程序化、非逻辑的内置模型,它很难正确使用。事实上,您的程序在许多模式下都不工作,这使得理解Prolog的想法比必要的步骤更加复杂。@false:我发现您的评论有误导性。你真的希望一个新手能够理解抽象Prolog模型中令人不快的问题吗?你是在向一个新手建议一个高度程序化、非逻辑的内置模型,它很难正确使用。事实上,您的程序不适用于许多模式,这使得理解Prolog的思想比必要的步骤更加复杂。