我正在尝试编写一个谓词,它将获取一个列表,一个数字和一个变量,然后将列表的前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定义为空列表有关,但我不知道如何这样做,同时保留谓词的功能。
答案 0 :(得分: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
的约束,以从原始列表中精确取出适当数量的元素
答案 1 :(得分:0)
虽然the existing answer告诉您如何修复它,但我想尝试解释一下"垃圾变量"是
我得到
L1 = [1, 3, 5|_G2028]
。
列表中的变量_G2028
是一个未实例化的变量。翻译知道有些东西存在,但不知道是什么东西。
这是因为前两个条款,
take(_,0,_) :- !.
take([],_,_) :- !.
第一个说,转述,如果从任何东西拿走0件物品,你可以得到任何东西 第二个说,如果从空列表中取出任意数量的项目,你可以得到任何东西。
所以解释器会转到其中一个,因为它想评估take(Tail, N1, Result).
此时,Tail
已知,N1
已知,但Result
尚未知晓未知。在调用这些子句中的任何一个之后,解释器都不是更明智的,因为它们都没有告诉它Result
是什么。但目标成功了,所以它报告回来并告诉你L1 = [1, 3, 5|_G2028]
。