2016-09-14 66 views
2

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

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

它起源于这个thread,正是我想要的;不过,我还想了解我正在使用的代码。

回答

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
  • f由后缀贬低。

这不是suprising,因为这正是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. 

所以我们看到整个条款的含义(我已经改名变量,使列表由后缀  小号在变量名表示):

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

如果Ls是包含作为其第一元件H,随后元件Ts列表,其次是什么都没有,然后列表[H|Ts]L的powerset的成员。

通俗地说:

列表中的每一个非空前缀是幂的一员。

而从这个我们也看到powerset/2一个明显的遗漏,因为它出现在这个线程:该条款中没有得到的空 设置为幂的一员,更令人不安的是,他们没有接受空集为一组有效的,所以下面的错误失败

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

练习:正确powerset/2,以便它实际上成功了所有powerset的元素。