我有一个汽车列表(德语自动),第一个变量是牌照,第二个是速度:
[auto(eu-ts884, 69), auto(dn-gh184, 64), auto(ac-lj123, 72)].
现在我尝试编写一个平均谓词,但它失败并显示错误消息:
错误:参数没有充分实例化
到目前为止我的代码:
durchschnitt([], 0, 0).
durchschnitt([auto(_, X)|Tail], L, Y):-
Y is S/L,
L > 0,
cardinal([auto(_, X)|Tail], L),
sumKilometer([auto(_, X)|Tail], S).
sumKilometer([], 0).
sumKilometer([auto(_, X)|Tail], Sum) :-
sumKilometer(Tail, N),
Sum is N + X.
cardinal([], 0).
cardinal([_|Tail], Result) :-
cardinal(Tail, N),
Result is N + 1.
我的代码与post相当,尽管我无法弄清楚我的错误。
注意:sumKilometer
和cardinal
工作正常。
答案 0 :(得分:2)
你写道:
durchschnitt([], 0, 0).
durchschnitt([auto(_, X)|Tail], L, Y):-
Y is S/L,
L > 0,
cardinal([auto(_, X)|Tail], L),
sumKilometer([auto(_, X)|Tail], S).
第一个问题是,当您致电durchschnitt([auto(foo,2)],L,Y)
时, L
是一个自由变量。因此,无法计算Y is S/L
,因为此处S
和L
都未知。
但您可以使用:
durchschnitt([], 0, 0).
durchschnitt([auto(_, X)|Tail], L, Y):-
cardinal([auto(_, X)|Tail], L),
sumKilometer([auto(_, X)|Tail], S),
Y is S/L.
因此,您可以计算L
和S
已知之后的平均值。此外,您不会将列表与[auto(_,X)|Tail]
等统一在一起。像A = [_|_]
这样的简单检查就足够了:
durchschnitt([], 0, 0).
durchschnitt(A, L, Y):-
A = [_|_],
cardinal(A, L),
sumKilometer(A, S),
Y is S/L.
这也将减少打包和解包所花费的时间。
您可以构造一个同时计算三个谓词的谓词(因此不会在列表上循环两次)。您只需使用 accumulators ,例如:
durchschnitt(A,L,Y) :-
durchschnitt(A,0,0,L,Y).
这里第二个和第三个元素分别是运行总和和长度。
现在durchschnitt/5
,有两种情况。在第一种情况下,我们已到达列表的末尾,因此我们必须计算平均值并将其返回,如:
durchschnitt([],S,L,L,Y) :-
(L \= 0
-> Y is S/L
; Y = 0).
所以我们使用if-then-else检查长度是否与0
不同(如果列表中没有auto
s,我们返回0
平均值。
在递归的情况下,我们简单地递增运行长度并更新运行总和,如:
durchschnitt([auto(_,Si)|T],RS,RL,L,Y) :-
RSN is RS+Si,
L1 is L+1,
durchschnitt(T,RSN,L1,L,Y).
或者把它放在一起:
durchschnitt(A,L,Y) :-
durchschnitt(A,0,0,L,Y).
durchschnitt([],S,L,L,Y) :-
(L \= 0
-> Y is S/L
; Y = 0).
durchschnitt([auto(_,Si)|T],RS,RL,L,Y) :-
RSN is RS+Si,
L1 is L+1,
durchschnitt(T,RSN,L1,L,Y).