【问题标题】:Package Searching in PrologProlog 中的包搜索
【发布时间】:2012-07-27 16:03:58
【问题描述】:

我有以下包:

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).

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

【问题讨论】:

    标签: list search comparison prolog package


    【解决方案1】:

    我已经简化了你的程序,使用 ISO Standard Order of Terms 进行比较:

    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 中,分隔符周围有一个 easier way to split 原子,但我没有在上面的代码中使用它。

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

    最后一点:compare 对于复杂项(包括列表)按预期工作,如果您没有一些奇怪,就没有必要自己编写> 要求。您可以改为考虑 规范化 版本表示:即“3”应该在传递之前规范化为“3.0.0”。

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

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

    【讨论】:

    • 感谢您的回答!!为了更正我的谓词,实际上我在发帖之前确实尝试过这种方式,但它根本不起作用。似乎上面的“cmp_list/3”谓词不正确。请问你知道怎么解决吗?
    • 为什么不使用 compare/3?你的 Prolog 没有?
    • 我不太明白 compare/3,compare/3 中的原子“R”是什么意思??
    • R 代表关系,它是您设置的符号,以“通常”的方式使用谓词,或保留变量,从 Prolog 中获取关系。
    猜你喜欢
    • 2012-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多