List Prolog返回值比较

List Prolog返回值比较,list,prolog,return,List,Prolog,Return,我正在学习逻辑编程的基础知识。 我解决了一些练习,现在我很难创建一个包含两个参数的函数,一个非空列表列表,其中的元素连接在一起形成第二个参数 当我创建了一个函数来连接列表中的元素时: concat([[]|L],L3):- concat(L,L3). concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!. 现在,我需要知道的是如何获取该函数的返回值,并将其与列表(函数的第二个参数)进行比较。Prolog没有过程编程语言意义上的函数或返回

我正在学习逻辑编程的基础知识。 我解决了一些练习,现在我很难创建一个包含两个参数的函数,一个非空列表列表,其中的元素连接在一起形成第二个参数

当我创建了一个函数来连接列表中的元素时:

concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!.

现在,我需要知道的是如何获取该函数的返回值,并将其与列表(函数的第二个参数)进行比较。

Prolog没有过程编程语言意义上的函数或返回值。它有断言关系的谓词。它有一些术语,包括带有一些限制的变量:

  • 所有变量都是局部变量,并且
  • 变量一旦赋值,就不再是变量。这就是为什么它被称为统一
所以

如果您想要一个谓词,它将接受两个列表并生成它们的连接,那么需要向它传递第三个变量。您可以这样调用它:

concat([a,b],[c,d],X).
concat( Prefix , Suffix,  [a,b,c,d] ).
它断言
X
[a,b]
[c,d]
的串联。Prolog的推理引擎随后将评估断言的真假

大多数递归问题都有一些特殊情况和更一般的情况。这样一个
concat/3
谓词的实现可能看起来像这样(通过注释来解释它在做什么)

  • 首先,我们有一个特殊的(终止的)情况:如果左边的列表是空的,那么连接就是右边的列表

    concat([],Bs,Bs)

  • 接下来,我们有一个一般情况:如果左边的列表是非空的,我们需要将它预加到我们正在构建的凹面上(然后向下递归)

    concat([A|As],Bs,[A|Cs]):- 混凝土(As、Bs、Cs)

就这些了,有两个。您还将注意到它是双向的:将列表拆分也非常方便。这样调用它:

concat([a,b],[c,d],X).
concat( Prefix , Suffix,  [a,b,c,d] ).
在回溯过程中,将产生所有可能的方式,将
[a,b,c,d]
拆分为前缀和后缀:

Prefix    Suffix
--------- ---------
[]        [a,b,c,d]
[a]       [b,c,d]
[a,b]     [c,d]
[a,b,c]   [d]
[a,b,c,d] []

这是一种允许在子列表中只包含单个元素,但不允许空子列表的方法:

concat([[L]], [L]).
concat([[H],L|T], [H|R]) :- concat([L|T], R).
concat([[H1,H2|T]|LT], [H1|RT]) :- concat([[H2|T]|LT], RT).
这里避免空列表的方法是在recursive子句中调用两个head元素,在base case中调用一个单独的元素列表。这会阻止空的子列表按照原始帖子评论中的要求成功

如果您有一个已经实例化的变量,
Y
,并且您想知道它是否是串联列表的结果,
LL
,您只需查询:

concat(LL, Y).
如果
Y
是列表
LL
false
的串联,则为
true
。您不必“返回并比较”(例如,在C中,您可能会说,
concat(LL)==Y
,或
concat(LL,X);if(X==Y)…
)。这是因为
concat
是两个参数之间定义的关系,它确定是否可以通过遵循所述规则(谓词的子句)进行
true

如果您已经获得了一个结果,并且想要确定它是否可统一到另一个变量,
Z
,那么您可以说:

concat(X, Y), Y = Z.

请注意,在Prolog中,
concat(X,Y)=Z
对于确定谓词的结果是否等于
Z
是不正确的,因为它不是返回值的函数。

您只需要基本情况

concat([],[]).
concat([[]|L],L3):- concat(L,L3).
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3).
它也适用于空(子)列表。
我已经删除了无用的剪切。

Prolog没有返回值的函数。Prolog具有定义其参数之间关系的谓词。有点不清楚您要的是什么。如果
L
[]
,会发生什么情况?concat([],[])。但我认为这是没有必要的,因为我用!中断了递归!。递归消除了解决方案。它没有添加它们。而且它不能代替一个合适的终端案例,因为这个案例必须依靠自身的力量取得成功。
concat([]],L)
的结果应该是什么?在我的程序中,这应该是错误的,因为第一个参数不能是空列表的列表。如果我在我的程序中尝试它,它是L=[]谢谢你的回答,但这不是我要找的。OP在他对其帖子的一条评论中指出,他不希望空的子列表成功。这很完美,只是一点。我昨天在想这件事,我得出的结论和你差不多。但是我在concat([H],L | T],[H | R])后面加了一个中断“!”:-concat([L | T],R)。强制谓词只返回一个true或false。我创建了一个:compare(X,Y):-concat(X,C),C=Y,只是为了知道第二个参数适合第一个参数。例如:比较([[1,2],[3,4]],L)。应该是L=[1,2,3,4]。@Saturnino,除非绝对必要,否则我倾向于保留这个切口。如果您在本例中包含break,那是因为您正试图使谓词以更强制的方式运行(给它一个输入,然后得到一个输出)。但是,在没有中断的情况下,诸如
concat(L[1,2,3])。
之类的查询将显示连接到
[1,2,3]
L
的所有可能值。有了切割,这个查询将不会产生所有正确的答案,因为它们已经被切割剪掉了。这就是使用削减的问题:它们可以消除可能的替代解决方案。小心使用。你是对的,在这种情况下,cut对我有效,因为我试图知道compare的第二个参数的值,这是唯一可能的解决方案。但是在这种情况下,我想知道第一个参数的值,正如你在上面所揭示的,这个切割是错误的。