1

我有以下软件包:

package('python', '2.6.5').
package('python', '2.5.4').
package('python', '1.5.2').
package('python', '3.1.0').

我在 Prolog 中编写了一些基本功能,它们如下:

% Integer-like-atom <-> integer
atom_integer(Atom, Int) :- atom_chars(Atom, C), number_chars(Int, C).

% Split an atom around a separator
% split, split2, split3 from: http://gollem.swi.psy.uva.nl/SWI-Prolog/mailinglist/archive/old/0164.html
split(A,B,C):-
 atom_chars(A,AC),
 atom_chars(B,BC),
 append(BC,AC,BAC),
 split3(AC,BAC,ABAC),
 split2(AC,ABAC,C), !.

split3(AC,BAC,NewABAC):-
 append(AC,ABAC,BAC),split3(AC,ABAC,NewABAC).
split3(_,ABAC,ABAC).

split2(_,[],[]).
split2(X,Y,[A|O]):- 
 append(Z,X,ZX),append(ZX,R,Y),atom_chars(A,Z),
 split3(X,R,NewR),
 split2(X,NewR,O).

split_version(Ver, VParts) :- split('.', Ver, VParts).

%%% integer_list/2
integer_list([], []).
integer_list([Lst1|RLst1], [Lst2|RLst2]) :-
    atom_integer(Lst1, Lst2),
    integer_list(RLst1, RLst2).


%%% cmp_list/3
cmp_list([A], [B], Cmp) :-
    A > B,
    Cmp = gt.

cmp_list([A], [B], Cmp):-
    A < B,
    Cmp = lt.

cmp_list([A], [B], Cmp):-
    A >= B,
    Cmp = ge.

cmp_list([A], [B], Cmp):-
    A =< B,
    Cmp = le.

cmp_list([], [B], Cmp):-
    Cmp = le.

cmp_list([], [B], Cmp):-
    Cmp = lt.

cmp_list([A], [], Cmp):-
    Cmp = ge.

cmp_list([A], [], Cmp):-
    Cmp = gt.

cmp_list([X|XS], [Y|YS], Cmp):-
    X > Y,
    cmp_list([X], [Y], Cmp).

cmp_list([X|XS], [Y|YS], Cmp):-
    X == Y,
    cmp_list(XS, YS, Cmp).


%%% cmp_version/3
cmp_version(V1, V2, Cmp):-
    split_version(V1, Lst1),
    split_version(V2, Lst2),
    integer_list(Lst1, IntLst1),
    integer_list(Lst2, IntLst2),
    cmp_list(IntLst1, IntLst2, Cmp).

现在,我想编写一个 satis_req/3 函数来获取以下内容:

?- satis_req('python', '3', le, V).
V = '2.6.5' ;
V = '2.5.4' ;
V = '1.5.2' .

?- satis_req('python', '2.5.4', gt, V).
V = '2.6.5' ;
V = '3.1.0' .

下面的代码是我自己写的,但是调用的时候出现了错误。

satis_req(Language, V1, Cmp, V2):-
    V2 = package(Language, V),
    write(V2),
    nl,
    cmp_version(V1, V2, Cmp).

任何人都可以帮助我使这个功能正确吗?提前致谢!!

4

1 回答 1

0

我已经简化了你的程序,使用 ISO标准术语顺序进行比较:

package(python, '2.6.5').
package(python, '2.5.4').
package(python, '1.5.2').
package(python, '3.1.0').

satis_req(Language, V1, Cmp, V2):-
    package(Language, V2),
    compare(R, V2, V1),
    match(Cmp, R).

match(lt, (<)).
match(gt, (>)).
match(le, (=<)).
match(le, (<)).
match(ge, (>=)).
match(ge, (>)).
match(eq, (==)).
match(ne, (\==)).
match(ne, (<)).
match(ne, (>)).

测试:

?- satis_req('python', '3', le, V).
V = '2.6.5' ;
V = '2.5.4' ;
V = '1.5.2' ;
false.

?- satis_req('python', '2.5.4', gt, V).
V = '2.6.5' ;
V = '3.1.0'.

在 SWI-Prolog 中,有一种更简单的方法可以在分隔符周围拆分原子,但我没有在上面的代码中使用它。

?- atomic_list_concat(L, '.', '2.5.4').
L = ['2', '5', '4'].

最后一点:比较复杂术语(包括列表)的预期工作,如果您没有一些奇怪的要求,则没有必要编写自己的。相反,您可以考虑一个规范化的版本表示:即“3”应该在传递之前规范化为“3.0.0”。

无论如何,这里对您的最后一个谓词进行更正(Prolog 没有功能):

satis_req(Language, V1, Cmp, V2):-
    package(Language, V2),
    write(V2),
    nl,
    cmp_version(V1, V2, Cmp).
于 2012-07-30T12:39:10.917 回答