5

我意识到这会有限制,但是有没有一种合理的方法可以在 Prolog 代码中放入条件指令,以便它在 GNU 或 SWI 中合理地工作?sumlist我在考虑至少最简单的情况,即SWI 和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.

或者什么不是。两种语言中都存在条件指令,但似乎没有提供执行此类操作所需的条件。我可能遗漏了一些手动搜索没有出现的东西。

4

3 回答 3

5

GNU Prolog 和 SWI-Prolog 的最新版本都定义了一个名为的标志dialect(顺便说一句,这是一个事实上的标准,因为它由大多数 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.
于 2013-06-11T09:08:53.137 回答
1

Portability is one of most weak points of Prolog - the ISO standard defines current_prolog_flag/2, but not lists among flags the 'name' of implementation.

I used the following code to switch among SWI and YAP

swi :- prolog_impl(swi).
yap :- prolog_impl(yap).

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

and then used it like

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

but GNU doesn't define version_data. Then that code should be extended more or less like

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

(note: not tested)

To test existence of a builtin there is predicate_property/2 (AFAIK not ISO) and you will need to experiment - as usual - the determine the actual behaviour.

OT: sumlist/2 is deprecated, there is sum_list/2

于 2013-06-11T06:06:03.053 回答
0

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

prolog_impl(K) :-
    current_prolog_flag(version_data, F),
    functor(F, K, _).
于 2013-06-11T16:33:40.177 回答