【问题标题】:Prolog return value comparationProlog返回值比较
【发布时间】:2015-03-14 13:16:29
【问题描述】:

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

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

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

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

【问题讨论】:

  • Prolog 没有带有返回值函数。 Prolog 有 predicates 来定义其参数之间的 relations。有点不清楚您要的是什么。
  • 如果L[] 会发生什么?
  • concat([],[])。但我认为没有必要,因为我用 ! 打破了递归。
  • 递归消除了解决方案。它不添加它们。而且它不能替代适当的终端案例,因为该案例必须自行成功。 concat([[]], L) 的结果应该是什么?当你在你的程序中尝试它是什么?
  • 在我的程序中应该是假的,因为第一个参数不能是空列表的列表。如果我在我的程序中尝试它是 L=[ ]

标签: list prolog return


【解决方案1】:

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

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

所以....

如果您想要一个包含两个列表并产生它们连接的谓词,您需要将第三个变量传递给它。你可以这样调用它:

concat([a,b],[c,d],X).

断言X[a,b][c,d] 的串联。然后,Prolog 的推理引擎将评估断言的真假。

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

  • 首先,我们有一个特殊的(和终止的)情况:如果左侧列表为空,则连接就是右侧列表。

    concat( [] , Bs , Bs ).

  • 接下来,我们有一个一般情况:如果左侧列表非空,我们需要将它添加到我们正在构建的连接之前(然后向下递归。)

    concat( [A|As] , Bs , [A|Cs] ) :- 连接(As,Bs,Cs)。

仅此而已。您还会注意到它是双向的:也非常乐意将列表分开。像这样调用它:

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] []

【讨论】:

  • 感谢您的回答,但这不是我要找的。​​span>
【解决方案2】:

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

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).

这里避免空列表的方法是在递归子句中调用两个头元素,在基本情况下调用一个单独的元素列表。这可以防止空子列表按照原始帖子的 cmets 中的要求成功。

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

concat(LL, Y).

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

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

concat(X, Y), Y = Z.

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

【讨论】:

  • 这很完美,只是一点。我昨天正在考虑这个问题,我或多或少地得出了与您相同的结论。但我添加了一个休息“!”在 concat([[H],L|T], [H|R]) 之后:- concat([L|T], R)。强制谓词只返回一个真或假。我创建了一个: 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]). 之类的查询将显示L 的所有可能值,它们连接到[1,2,3]。切割到位后,此查询将不会产生所有正确答案,因为它们已被切割修剪。这就是使用削减的问题:它们可以消除可能的替代解决方案。谨慎使用。
  • 你是对的,在这种情况下,cut 对我有用,因为我试图知道 compare 的第二个参数的值,它是唯一一种可能的解决方案。但在我想知道第一个参数的值的情况下,正如您在上面所揭示的那样,切割将是错误的。
【解决方案3】:

你只需要基本情况​​

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

它也适用于空(子)列表。 我已经删除了无用的剪辑。

【讨论】:

  • OP 表示,他深埋在他的一个 cmets 到他的帖子中,他不希望空子列表成功。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
相关资源
最近更新 更多