Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making Prolog code that works in GNU and SWI

I realize there are going to be limits to this, but is there a reasonable way to put in conditional directives in Prolog code so that it an work reasonably in either GNU or SWI? I'm thinking at least the simplest cases, where built-in predicates such as sumlist in SWI and sum_list in GNU don't match each other in spelling. Or SWI has assert but GNU does not. So it would be nice to have something like:

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

Or simply:

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

Or what not. The conditional directives exist in both languages, but the seem to stop just short of providing the conditionals needed to do this sort of thing. I'm probably missing something that a manual search didn't turn up for me.

like image 391
lurker Avatar asked Jun 10 '13 23:06

lurker


2 Answers

Both recent versions of GNU Prolog and SWI-Prolog define a flag named dialect (which, btw, is a de fact standard as it's implemented by most Prolog systems) that you can use in the conditional compilation directives:

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

Thus, simple write something like:

:- if(current_prolog_flag(dialect, swi)).

    % SWI-Prolog specific code

:- elif(current_prolog_flag(dialect, gprolog)).

    % GNU Prolog specific code

:- else.

    % catchall code

:- endif.
like image 83
Paulo Moura Avatar answered Oct 31 '22 17:10

Paulo Moura


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

like image 23
CapelliC Avatar answered Oct 31 '22 15:10

CapelliC