我基本上试图创建'我自己'版本的@< prolog中的运算符,即at_less(F1,F2)的调整,如果F1 @它返回true
一些示例输入:
?- at_less(1.2,0)
yes
?-at_less(0,1.2)
no
?-at_less(f(1,2,a),f(1,2,b)).
yes
显然我不想使用@<运营商,因为这将是多余的:) 我可以理解如何比较两个原子,比如
%atom_pr(+A1,+A2): A1 @< A2, where A1 and A2 are atoms.
atom_pr(L1,L2):-
atom_codes(L1,First), %atom codes for first
atom_codes(L2,Second),%atom codes for second
code_compare(First,Second). %compare the codes, return true or false
code_compare([HF|TF],[HS|TS]):-
( HF=HS ->
code_compare(TF,TS)
;
HF<HS ->
true
;
fail
).
code_compare([],X):-
true.
code_compare([],[]).
%(I understand this is probably not the most efficient way of going about this, but I'm %just beginning!)
我能为所有常数做些类似的东西,而不仅仅是原子吗?是否有类似于atom_codes / 2的命令?如果没有,我唯一能想到的就是把它分成很多if - &gt; else语句,检查第一个是原子而第二个不是等等,但这似乎是一种单调乏味/差的方法呢?
提前感谢您的帮助!
编辑:感谢下面的帮助,我得到了一个正常运行的程序(至少从我能说的内容)。我把它放在下面的代码中,以防其他人在这里徘徊。但我认为这是非常低效的,所以还有很大的改进空间:)
%flat_pr(+F1, +F2): F1@<F2, where F1 and F2 are flat ground terms
flat_pr(F1,F2):-
( compound(F1) -> %these ifs here to check what type F1 and F2 are
( compound(F2) -> %comparing/succeeding/failing as appropriate
compound_compare(F1,F2) %(atom>integer>float>compound)
; % I believe these ifs could definitely be cut down though
( atom(F2) ->
true
;
( float(F2) ->
true
;
( integer(F2) ->
true
)
)
)
)
)
;
( atom(F1) ->
( compound(F2) ->
false
;
( atom(F2) ->
atom_pr(F1,F2)
;
( float(F2) ->
false
;
( integer(F2) ->
false
)
)
)
)
)
;
( float(F1) ->
( compound(F2) ->
false
;
( atom(F2) ->
true
;
( float(F2) ->
number_pr(F1,F2)
;
( integer(F2) ->
true
)
)
)
)
;
fail
)
;
( integer(F1) ->
( compound(F2) ->
false
;
( atom(F2) ->
true
;
( float(F2) ->
false
;
( integer(F2) ->
number_pr(F1,F2)
)
)
)
)
)
.
compound_compare(F1,F2):- %compares compounds (arity first)
functor(F1,N1,A1), %get arity
functor(F2,N2,A2),
( A1<A2 -> %compare arity
true
;
( A1>A2 ->
false
)
;
( A1=A2 -> %if arity the same
F1 =.. L1, %compound -> list
F2 =.. L2,
list_compare(L1,L2) %compare the lists
)
)
.
list_compare([],[]). %base case
list_compare([H|T],[H1|T1]):-
( flat_pr(H,H1) -> %if H@<H1
list_compare(T,T1) %compare Tails
;
false %else false
)
.
atom_pr(L1,L2):-
atom_codes(L1,First), %atom codes for first
atom_codes(L2,Second),%atom codes for second
code_compare(First,Second). %compare the codes, return true or false
number_pr(L1,L2):- %simple number comparison...straight forward
( L1=<L2 ->
true
;
fail
).
code_compare([HF|TF],[HS|TS]):- %just runs through atom codes
( HF=HS ->
code_compare(TF,TS)
;
HF<HS ->
true
;
fail
).
code_compare([],X):-
true.
code_compare([],[]).
我很想看到改善这个的方法!干杯
答案 0 :(得分:1)
不确定BIN-Prolog,但在SWI-Prolog中,atom_codes可以解决问题:
?- atom_codes('jack\&^',K).
K = [106, 97, 99, 107, 38, 94].
?- atom_codes('17.2345',K).
K = [49, 55, 46, 50, 51, 52, 53].
<强>更新强> 如果你需要比较术语,1)冻结它们(进一步参见)使术语接地,2)使用unif(= ..)将术语转换为列表,例如,f(1,2)变为[f, 1,2],然后对于每个元素:a)如果它是原子或数字,则使用atom_codes; b)如果是一个术语,则递归地应用相同的过程。
冻结确保变量按其外观顺序进行比较。通过“冻结”,我的意思是从经典的Sterling和Shapiro的书“Prolog的艺术”中得到以下谓词:
numvars('#VAR'(N),N,N1) :- N1 is N+1.
numvars(Term,N1,N2) :- nonvar(Term), functor(Term,_,N),
numvars(0,N,Term,N1,N2).
numvars(N,N,_,N1,N1).
numvars(I,N,Term,N1,N3) :- I<N, I1 is I+1,
arg(I1,Term,Arg), numvars(Arg,N1,N2),
numvars(I1,N,Term,N2,N3).
frz(A,B) :- frz(A,B,0).
frz(A,B,Min) :- copy_term(A,B), numvars(B,Min,_),!.