Создание Пролог-кода, работающего в GNU и SWI



Я понимаю, что этому есть пределы, но есть ли разумный способ поместить условные директивы в Пролог-код, чтобы он работал разумно в GNU или SWI? Я думаю, по крайней мере, о простейших случаях, когда встроенные предикаты, такие как sumlist в SWI и sum_list в GNU, не совпадают друг с другом по орфографии. Или 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.


Или что-то еще. Условная директива существуют в обоих языках, но, кажется, останавливаются только на том, чтобы обеспечить условия, необходимые для выполнения такого рода вещей. Я, вероятно, упустил что-то, что ручной поиск не нашел для меня.

572   3  

3 ответов:

Обе последние версии GNU Prolog и SWI-Prolog определяют флаг с именем dialect (который, кстати, является стандартом de fact, поскольку он реализован в большинстве систем 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.

Переносимость является одним из самых слабых мест пролога - стандарт 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 (Насколько мне известно, не ISO) и вам нужно будет поэкспериментировать-как обычно-определить фактическое поведение.

OT: sumlist/2 устарел, есть sum_list/2

Флаг dialect является наиболее подходящим для проверки базовой системы. Однако GNU Prolog также предоставляет version_data. Кстати: лучшее определение для prolog_impl с использованием version_data:

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

Comments

    Ничего не найдено.