首页 文章

制作适用于GNU和SWI的Prolog代码

提问于
浏览
3

我意识到这将有限制,但有没有合理的方法在Prolog代码中放入条件指令,以便它在GNU或SWI中合理地工作?我在考虑至少最简单的情况,其中内置谓词如SWI中的 sumlist 和GNU中的 sum_list 在拼写中彼此不匹配 . 或者SWI有 assert 但GNU没有 . 所以有这样的东西会很好:

:- if($SWI).
SWI version of stuff
:- else.
GNU version of stuff
:- endif.

或者干脆:

:- if(not_a_builtin(sumlist))
sumlist(L, S) :- sum_list(L, S).
:- endif.

或者不是 . 条件指令存在于两种语言中,但似乎停止提供执行此类操作所需的条件 . 我可能错过了一些手动搜索没有出现的东西 .

3 回答

  • 0

    GNU Prolog和SWI-Prolog的最新版本都定义了一个名为 dialect 的标志(其中,btw,它是大多数Prolog系统实现的事实标准),您可以在条件编译指令中使用它:

    $ gprolog
    GNU Prolog 1.4.4 (64 bits)
    Compiled Apr 23 2013, 17:24:33 with /opt/local/bin/gcc-apple-4.2
    By Daniel Diaz
    Copyright (C) 1999-2013 Daniel Diaz
    | ?- current_prolog_flag(dialect, Dialect).
    
    Dialect = gprolog
    
    yes
    
    $ swipl
    Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.3.16-6-g9c0199c-DIRTY)
    Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
    SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
    and you are welcome to redistribute it under certain conditions.
    Please visit http://www.swi-prolog.org for details.
    
    For help, use ?- help(Topic). or ?- apropos(Word).
    
    ?- current_prolog_flag(dialect, Dialect).
    Dialect = swi.
    

    因此,简单的写道:

    :- if(current_prolog_flag(dialect, swi)).
    
        % SWI-Prolog specific code
    
    :- elif(current_prolog_flag(dialect, gprolog)).
    
        % GNU Prolog specific code
    
    :- else.
    
        % catchall code
    
    :- endif.
    
  • 3

    可移植性是Prolog的最弱点之一 - ISO标准定义了current_prolog_flag / 2,但没有列出'name'实现的标志 .

    我使用以下代码在SWI和YAP之间切换

    swi :- prolog_impl(swi).
    yap :- prolog_impl(yap).
    
    prolog_impl(K) :-
        F =.. [K,_,_,_,_],
        current_prolog_flag(version_data, F).
    

    然后就像使用它一样

    :- if(swi).
    
     gen_hash_lin_probe(Key, HashTable, Value) :-
        arg(_, HashTable, E),
        nonvar(E),
        E = Key-Value.
    
    :- elif(yap).
    
     gen_hash_lin_probe(Key, HashTable, Value) :-
        HashTable =.. [htlp|Args],
        nth1(_, Args, E),
        nonvar(E),
        E = Key-Value.
    
    :- endif.
    

    但是GNU没有定义 version_data . 然后该代码应该或多或少地扩展

    ...
       catch(current_prolog_flag(version_data,F),_,K = gnu).
    

    (注意:未经测试)

    为了测试内置的存在,有predicate_property / 2(AFAIK而不是ISO),你需要像往常一样试验确定实际行为 .

    OT:不推荐使用sumlist / 2,有sum_list / 2

  • 1

    dialect 标志最适合测试底层系统 . 但是,GNU Prolog还提供 version_data . BTW: prolog_impl 使用 version_data 的更好定义是:

    prolog_impl(K) :-
        current_prolog_flag(version_data, F),
        functor(F, K, _).
    

相关问题