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'].

最後の注意:リストを含む複雑な用語の場合、 compareは期待どおりに機能します。特殊な要件がない場合は、独自に記述しても意味がありません。代わりに、正規化されたバージョン表現について考えることができます。つまり、「3」は、それを渡す前に「3.0.0」に正規化する必要があります。

とにかく、ここで最後の述語の修正 (Prolog has not functions ):

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