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

时间:2013-06-10 23:57:39

标签: prolog swi-prolog portability gnu-prolog iso-prolog

我意识到这会有限制,但有没有合理的方法在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 :(得分:3)

最近版本的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.

答案 1 :(得分:1)

可移植性是Prolog的最弱点之一 - ISO标准定义了current_prolog_flag / 2,但列出了标记中的名称'实施。

我使用以下代码在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

答案 2 :(得分:0)

dialect标志最适合测试底层系统。但是,GNU Prolog还提供了version_data。顺便说一句:使用prolog_impl version_data的更好定义是:

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