序言:汇总列表中的元素

时间:2018-07-02 23:07:04

标签: prolog

我对序言很陌生,我正在尝试对列表元素进行汇总。 到目前为止,我有这个:

     sum([],_,_). %base case
     sum([H|T], Y, _X):-
        X2 is H + Y,
        sum(T,X2,X2).

使用sum([1,2,3,4],0,X)进行测试会导致错误,但是我不确定这段代码有什么问题。有人可以指出我正确的方向吗?

1 个答案:

答案 0 :(得分:0)

您提供的代码比您想像中的更接近工作,但是存在一些问题。

首先,Prolog谓词不是函数,它们不会像其他语言的函数那样返回结果。谓词则声明什么是正确的。稍后,您可以进行序言查询,它会尽力使它们成为现实。

例如,当左参数为列表,而右参数为具有列表长度的int时,对length/2的调用为true:

?- length([1, 2, 3, 4], 4).
true.

?- length([1, 2, 3, 4], X).
X = 4.

?- length(X, 2).
X = [_2300, _2306].

回顾第一行:

sum([],_,_). %base case

这表示“ sum / 3始终为true,只要第一个元素为空列表”。您可以对此进行测试:

?- sum([], -20, hello).
true.

那可能不是你想要的。

我不确定如何在不放弃答案的情况下放置其余内容,但请看一下该子句在说什么:

 sum([H|T], Y, _X):-
    X2 is H + Y,
    sum(T,X2,X2).

“ {sum([H|T], Y, WhoCaresIllNeverUseThisVariable)是真的,如果我们可以再次证明sum(T, H+Y, H+Y)是真的”。

好一点,最后一个参数有点奇怪,因为您在两个子句中都将其分配给匿名变量(__X)。您要说的是,“第三个参数永远不会重要,应该从字面意义上匹配任何用途”。我认为那不是你想说的。

第二点,我不知道您是否意识到这一点,但是,您实际上是在计算总和!在尝试使sum([1, 2, 3, 4], 0, X)为真时,Prolog将遍历列表并将每个元素添加到中间参数(累加器)中。求和部分起作用!您没有做的是从此谓词中提取总和。

通常,在Prolog中,您可以通过将其作为附加参数来“返回”结果。您可以通过这种方式查看length / 2。这是您自己编写的一种方法:

my_length([], 0).
my_length([_|Rest], Length) :-
  my_length(Rest, Length1),
  Length is Length1 + 1.

此函数仅在谓词的第二个参数是数组的长度时才为true,从而“返回”数组的长度。