理解追加语法

时间:2016-09-14 12:54:30

标签: prolog append

我在理解这段代码时遇到了一些麻烦。

powerset(L, [H|T]):-
  append([H|T], _, L).

它起源于此thread并完全符合我的要求;但是,我也想了解我正在使用的代码。

1 个答案:

答案 0 :(得分:3)

让我们首先单独考虑该条款的单一目标:

?- append([H|T], _, L).

这是什么意思?使用纯Prolog代码,有一种方便的方式可以更多地了解关系:只需在查询上发布查询,看看解决方案是什么样的。

试一试!例如:

?- append([H|T], _, L).
L = [H|_1282],
T = [] ;
L = [H, _1078|_1096],
T = [_1078] ;
L = [H, _1078, _1084|_1108],
T = [_1078, _1084] ;
L = [H, _1078, _1084, _1090|_1120],
T = [_1078, _1084, _1090] ;
etc.

由此我们看到append/3的这个调用定义了它的参数之间的关系,我们看到了以下模式:

L总是包含:

  • H作为第一个元素
  • 后跟T
  • 中的所有元素
  • 后跟一个后缀。

这并不令人惊讶,因为这正是append([H|Ts], _, Ls)的含义:[H|Ts]后跟任何列表构成列表Ls

在您的具体用例中,L显然是实例化,因此后缀不能任意长。

例如:

?- append([H|T], _, [a,b,c]).
H = a,
T = [] ;
H = a,
T = [b] ;
H = a,
T = [b, c] ;
false.

所以我们看到了整个子句的含义(我已经重命名了变量,以便列表在变量名中用后缀 s 表示):

powerset(Ls, [H|Ts]):-
    append([H|Ts], _, Ls).

如果 Ls是一个列表,其中包含第一个元素H,后跟元素Ts,后跟任何内容然后列表[H|Ts]L的powerset的成员。

非正式:

  

列表中的每个非空前缀都是powerset的成员。

从这一点我们也看到了powerset/2的明显遗漏,因为它出现在这个帖子中:没有一个条款产生空集作为powerset的成员,甚至更多令人不安的是,他们都没有接受空集作为有效集,因此以下错误失败

?- powerset([], _).
false. % empty set is not a set?

练习:纠正powerset/2,以便它实际上对于powerset的所有元素都成功。