我想稍微扩展一下@WillemVanOnsem 的好答案。这是他发布的版本:
字节整数(字节列表,R):-
bytes_int(BytesList, 0, 0, R)。
字节整数([],_,R,R)。
字节整数([H|T],S0,R0,R):-
R1 是 R0 + H
所以,让我们尝试一些查询。一、问题中提供的测试用例:
?- bytes_int([42,121,56], I)。
我 = 3701034。
很好,它有效。所以让我们尝试一个更一般的情况,我查询 三个字节,但不指定它们的值:
?- bytes_int([A,B,C], I)。
错误:参数没有充分实例化
不幸的是,这不起作用:使用低级整数算术排除了这种更一般的用例。此限制适用于所有更一般的查询,即使它们有时可能会产生解决方案:
?- bytes_int(Bs, I)。
Bs = [],
我 = 0 ;
错误:参数没有充分实例化
至少 second 参数被完全实例化的更具体的情况如何:
?- bytes_int(Bs, 3701034)。
错误:参数没有充分实例化
不,在这种情况下,谓词也不能产生任何答案。
嗯,这一切都在意料之中,更多有命令倾向的程序员会在这一点上说。你认为我们是什么? 声明式程序员?
是的。
因此,我对上述版本进行了以下直接更改,以使其更具声明性:我将 (is)/2 替换为 (#=)/2。是的,我知道,40 年前的书没有这样做,但还是让我们这样做,看看我们会得到什么回报:
字节整数(字节列表,R):-
bytes_int(BytesList, 0, 0, R)。
字节整数([],_,R,R)。
字节整数([H|T],S0,R0,R):-
R1 #= R0 + H
让我们从最一般的查询开始,我们只要求任何答案:
?- bytes_int(Bs, I).
Bs = [],
我 = 0 ;
Bs = [_15310],
I#=_15310
不错!所以我们现在得到了更多的答案。事实上,我们现在可以测试非终止:
?- bytes_int(Bs, I),
false。
不终止
这个查询不终止的事实令人放心:由于谓词应该适用于任意长度的列表,它不能普遍终止。
让我们再试几个案例:
?- bytes_int([A,B,C], I)。
_3674#=A
上面就是这种情况:我们现在得到了所有答案的符号表示,这有时非常有用。
特别是,原始测试用例当然自然地遵循作为更一般查询的特例:
?- bytes_int([42,121,56], I)。
我 = 3701034。
这和以前完全一样。
所以还有一种情况需要测试:实例化的 second 参数怎么样?
?- bytes_int(Bs, 3701034).
Bs = [_5164],
3701034#=_5164
这至少会产生答案。我把它作为一个练习来改进这一点。回想一下,到目前为止,我所做的只是将(is)/2 替换为(#=)/2,仅此一项就已经大大增加了这种关系的普遍性。根据您的 Prolog 系统,您目前可能需要导入一个库才能从这个声明式整数运算中受益。