0

我正在尝试编写一个谓词,它将接受一个列表、一个数字和一个变量,然后将列表的前 N ​​个元素提供给变量。我能够做到这一点,但是在尝试使其更灵活以便它在到达列表末尾或 N 为 0 时停止时,我开始在列表末尾返回一个垃圾变量。这是我的代码:

take(_,0,_) :- !.
take([],_,_) :- !.
take([Head|Tail], Number, [Head|Result]) :- 
   Number > 0, 
   N1 is Number - 1, 
   take(Tail, N1, Result).

当我尝试使用时take([1,3,5,7], 3, L1),我得到了L1 = [1, 3, 5|_G2028]

我认为这与我没有将 Result 定义为空列表有关,但我不知道如何做到这一点,同时保持谓词的功能。

4

2 回答 2

1

将前 2 条规则更改为:

take(_,0,[]) :- !.
take([],_,[]) :- !.

从您的代码中,我可以看到这是一个谓词,当第三个参数是从第一个参数中的列表中获取前导元素尽可能多但小于指定的第二个参数的数量的结果take时,该谓词返回 true 。

因此,当第二个参数为 0 时,您可以将输出限制为[],因为您已达到限制。

当第一个参数是一个空列表时,您可以将输出限制为[],因为无论如何您都不能接受任何东西。

如果没有上述约束,这意味着当要获取的最大元素数为 0 或原始列表为空时,任何东西都是有效的。

或者,您可以在一个规则中编写所有内容:

take(In, Num, Out) :- append(Out, _, In), 
                      length(Out, OutLen), length(In, InLen),
                      OutLen is min(Num, InLen), !.

输出列表的长度是原始列表的长度 和 之间的最小值Num,它被用作append从原始列表中准确取出适当数量的元素的约束。

于 2012-12-03T06:29:35.207 回答
1

虽然现有答案告诉您如何解决它,但我想尝试解释一下“垃圾变量”是什么。

我明白了L1 = [1, 3, 5|_G2028]

列表中的那个变量_G2028, 是一个未实例化的变量。解释器知道某物在那里,但不知道该物是什么。

发生这种情况是因为前两个子句,

take(_,0,_) :- !.
take([],_,_) :- !.

第一个说,意译,如果你从任何东西中取 0 项,你就可以得到任何东西。
第二个说,如果你从一个空列表中取出任意数量的项目,你可以得到任何东西。

所以解释器得到其中之一,因为它想要评估take(Tail, N1, Result).在那个点上,Tail是已知的,N1是已知的,但Result仍然是未知的。在调用这些子句中的任何一个之后,解释器都不是更聪明,因为它们都没有告诉它是什么Result。但是目标成功了,所以它会报告回来并告诉你L1 = [1, 3, 5|_G2028]

于 2016-03-29T15:53:44.287 回答