我有一个谓词,它接收一个原子形式的二进制数,并返回一个十六进制代码列表。
<li ng-repeat ="list in lists | filter:{name:selected}">
<label ng-click="selected = list.name">
<input type="radio">
{{list.name}}{{selected}}
</label>
</li>
当我尝试从十六进制变为二进制时,我收到此错误:
?- binaryHex('11111111',X).
X = [f, f].
我希望两个变量都能产生正确的输出。这是代码。
?- binaryHex(X,[f,f]).
ERROR: atom_codes/2: Arguments are not sufficiently instantiated
谓词hex('0000',0). hex('0001',1). hex('0010',2). hex('0011',3).
hex('0100',4). hex('0101',5). hex('0110',6). hex('0111',7).
hex('1000',8). hex('1001',9). hex('1010',a). hex('1011',b).
hex('1100',c). hex('1101',d). hex('1110',e). hex('1111',f).
binaryHex(X,Y) :-
atom_codes(X,A),
binaryList(A,B),
binaryHex_(B,Y).
binaryList([],[]).
binaryList([A,B,C,D|Ds],[Y|Ys]) :-
atom_codes(Y,[A,B,C,D]),
binaryList(Ds,Ys).
binaryHex_([],[]).
binaryHex_([B|Bs],[H|Hs]) :-
hex(B,H),
binaryHex_(Bs,Hs).
和binaryHex_/2
中的变量都是双向的。程序因原始binaryList/2
中的实例化顺序而中断:binaryHex/2
必须在binaryList/2
之前,以便二进制到十六进制的原始任务能够正常工作。
我想如果我将十六进制列表转换为原子,这个问题就会复杂化。有哪些策略可以应对这种情况,以便在我继续编程时不会遇到实例化错误?任何关于何时无法实现的评论/答案也会受到鼓励。
答案 0 :(得分:4)
您的问题是您使用了错误的表示法。使用列表时,Prolog可以轻松处理您想要的内容而无需任何额外的工作。也就是说,字符列表(=长度为1的原子)。此外,使用dcg更为自然。啊,仅0
是一个整数,'0'
是相应的字符!
:- set_prolog_flag(double_quotes, chars). % More about double quotes
hexdigit('0') --> "0000".
hexdigit('1') --> "0001".
hexdigit('2') --> "0010".
hexdigit('3') --> "0011".
hexdigit('4') --> "0100".
hexdigit('5') --> "0101".
hexdigit('6') --> "0110".
hexdigit('7') --> "0111".
hexdigit('8') --> "1000".
hexdigit('9') --> "1001".
hexdigit( a ) --> "1010".
hexdigit( b ) --> "1011".
hexdigit( c ) --> "1100".
hexdigit( d ) --> "1101".
hexdigit( e ) --> "1110".
hexdigit( f ) --> "1111".
hexnum([]) -->
[].
hexnum([D|Ds]) -->
hexdigit(D),
hexnum(Ds).
binaryHex(Bin, Hex) :-
phrase(hexnum(Hex), Bin).
现在有一些示例用法:
?- binaryHex("11111111",X).
X = [f, f] ;
false.
?- binaryHex(H,"ff").
H = ['1', '1', '1', '1', '1', '1', '1', '1'].
?- use_module(double_quotes).
% double_quotes compiled into double_quotes 0.00 sec, 12 clauses
true.
?- binaryHex(H,"ff").
H = "11111111".
因此,只需使用列表即可获得“双向性”。 Coroutining在这里真的太过分了。更糟糕的是,使用原子的原始表示无法处理生成长度为8的所有位串的情况:
?- length(L,8), binaryHex(L,Hex).
L = "00000000",
Hex = "00" ;
L = "00000001",
Hex = "01" ;
L = "00000010",
Hex = "02" ;
L = "00000011",
Hex = "03" ...
证明没有长度为7的位串:
?- length(L,7), binaryHex(L,Hex).
false.
并证明以10
开头的位串不能与以f
开头的十六进制数字相对应。
?- binaryHex(['1','0'|L],[f|_]).
false.
你不能用原子和when/2
声明完成所有这些。
答案 1 :(得分:1)
我认为你要求的东西是不可能实现的 - 通常是在Prolog中。但是既然我answered提出了类似的问题,我建议尝试
binaryHex(X,Y) :-
when_2(atom_codes(X,A)),
when_2(binaryList(A,B)),
binaryHex_(B,Y).
binaryList([],[]).
binaryList([A,B,C,D|Ds],[Y|Ys]) :-
when_2(atom_codes(Y,[A,B,C,D])),
binaryList(Ds,Ys).
:- meta_predicate when_2(0).
when_2(P) :-
strip_module(P,_,Q),
Q =.. [_,A0,A1],
when((ground(A0);ground(A1)), P).
当然,/ 2必须由您的系统提供。