您的原始代码的问题是您试图在intToList/2 的递归子句中处理对sos/2 的调用。打破它(并将 intToList/2 重命名为更有意义的名称):
sosDigits(Number, SoS) :-
number_digits(Number, Digits),
sos(Digits, SoS).
这是你原来的sos/2,没有write,它似乎工作正常:
sos([], 0).
sos([H|T], S) :-
sos(T, S1),
S is (S1 + (H * H)).
或者更好的是,使用累加器进行尾递归:
sos(Numbers, SoS) :-
sos(Numbers, 0, SoS).
sos([], SoS, SoS).
sos([X|Xs], A, SoS) :-
A1 is A + X*X,
sos(Xs, A1, SoS).
您还可以使用maplist/3 和sumlist/2 实现sos/2:
square(X, S) :- S is X * X.
sos(Numbers, SoS) :- maplist(square, Numbers, Squares), sumlist(Squares, SoS).
您的intToList/2 需要使用累加器进行重构,以保持正确的数字顺序并摆脱对sos/2 的调用。如上所述重命名:
number_digits(Number, Digits) :-
number_digits(Number, [], Digits).
number_digits(Number, DigitsSoFar, [Number | DigitsSoFar]) :-
Number < 10.
number_digits(Number, DigitsSoFar, Digits) :-
Number >= 10,
NumberPrefix is Number div 10,
ThisDigit is Number mod 10,
number_digits(NumberPrefix, [ThisDigit | DigitsSoFar], Digits).
上述number_digits/2 也正确处理0,因此number_digits(0, Digits) 产生Digit = [0] 而不是Digits = []。
您可以使用-> ; 构造重写number_digits/3 的上述实现:
number_digits(Number, DigitsSoFar, Digits) :-
( Number < 10
-> Digits = [Number | DigitsSoFar]
; NumberPrefix is Number div 10,
ThisDigit is Number mod 10,
number_digits(NumberPrefix, [ThisDigit | DigitsSoFar], Digits)
).
那么它就不会留下选择点了。