Prolog - 参数未充分实例化。 lists/recursion

Prolog - Arguments are not sufficiently instantiated. lists/recursion

我试图从给定的列表中获取最大数量 'L' 并将其分配给一个变量,所以我曾经编写以下函数:

max(L,X):-
    [H|Q]=L,
    (X<H -> X=H),
    length(Q,QLEN),
    (QLEN>0 -> max(Q,X)),
    true.

但是在 SWI-Prolog 内编译代码并提示 max([1,2,3],X) 后,我得到以下错误:

ERROR: Arguments are not sufficiently instantiated ERROR: In: ERROR:
[9] _1064<1 ERROR: [8] max([1,2|...],_1092) at c:/users/kais/desktop/tp3.pl:24 ERROR: [7]

为什么我会收到这样的错误?

如评论中所述,您尝试将 H 与未实例化的 X 进行比较。这个问题的解决方案是创建一个谓词 maxList/3 并在 maxList/2 中调用它,如下所示:

maxList([H|T], Max) :-
    maxList(T, H, Max).

maxList([], Max, Max).
maxList([H|T], Max0, Max) :-
    Max1 is max(H, Max0),
    maxList(T, Max1, Max).

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

max/2 只是 returns 两个参数之间的最大值。 max/2 的一个可能实现是:

myMax(M,A,B):-
    A > B ->  M = A;
    M = B.

?- myMax(A,1,2).
A = 2.

顺便说一句,在 SWI 中已经有一个内置谓词来执行此操作,称为 max_list/2(我之前发布的代码实际上来自此实现):

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

另一种可能的实现,不依赖于辅助谓词,可以按照以下逻辑来完成:

  1. 如果列表只包含一个元素,则它是最大值。
  2. 如果列表L包含一个以上的元素,即它的形式是[H|T],而T的最大元素是M,那么如果 H>=ML 的最大元素将是 H,否则它将是 M

粗略的编码可能是:

maxList([X],X).
maxList([H|T],H) :-
  maxList(T,M),
  H >= M.
maxList([H|T],M) :-
  maxList(T,M),
  H < M.

这留下了改进的空间,但尊重上述逻辑和returns每个非空整数列表的最大元素。