5

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.

false
  • 10,264
  • 13
  • 101
  • 209
lurker
  • 56,987
  • 9
  • 69
  • 103

3 Answers3

5

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.
Paulo Moura
  • 18,373
  • 3
  • 23
  • 33
  • I was answering the same thing, then decided to test and my gprolog (not installed by source) raised an exception. `dialect` it's the way to go. – CapelliC Jun 11 '13 at 11:03
  • Even with this, there are limitations. The difference in Prolog versions that drives me a bit crazy is the `format` predicate, or the formatting of output in general. The ISO prolog output capability is quite lame and each version of Prolog seems to have branched off in their own direction, from what I've seen between SWI and GNU anyway. – lurker Jun 11 '13 at 12:17
  • There are indeed some unfortunate and incompatible differences in the format/2-3 predicates in GNU Prolog when compared with other Prolog systems that provide these predicates. But B-Prolog, CxProlog, ECLiPSe, SICStus Prolog, SWI-Prolog, XSB, and YAP (possibly some others) provide reasonable compatible implementations of these two predicates. – Paulo Moura Jun 11 '13 at 13:50
  • @mbratch: What are you missing in format/2,3 in GNU? I assume the - formatting instructions like `~20|`. That is really a bug in GNU you should report. – false Jun 11 '13 at 17:18
  • @mbratch: There is - unfortunately - also another limitation to this approach: It assumes that all systems can read the syntax of the other systems. If all systems would conform that would be true... – false Jun 11 '13 at 17:19
  • @false, I wouldn't say missing as much as very different. GNU format resorts to C `printf` format strings for anything beyond the most simple output. SWI (for format) uses the tilde notation and expands it to be more than what GNU offers. SWI then has `writef` with a whole different set of format conventions using percent (%). – lurker Jun 11 '13 at 17:47
  • @mbratch: format/2,3 comes from Quintus in the 1980s. You'll get uniformity only if you insist... – false Jun 11 '13 at 18:19
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

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • `sum_list/2` doesn't work for me in SWI-Prolog 6.0.2. I get, `ERROR: toplevel: Undefined procedure: sum_list/2 (DWIM could not correct goal)`. `sumlist/2` works. – lurker Jun 11 '13 at 10:57
  • Since I'm using preferentially Linux, I keep SWI-Prolog updated building from source. Probably sumlist/2 gone in backcomp library recently. I just reported what's noted from the doc page. Sorry for the noise. – CapelliC Jun 11 '13 at 11:07
  • CapelliC, I always appreciate your answers. Thanks for the heads-up on `sumlist`. No need to apologize. I'm using Linux as well, but am just using the latest available `yum` install. – lurker Jun 11 '13 at 11:08
0

The dialect flag is the most appropriate to test the underlying system. However, GNU Prolog also provides version_data. BTW: a better definition for prolog_impl using version_data is:

prolog_impl(K) :-
    current_prolog_flag(version_data, F),
    functor(F, K, _).
didou
  • 692
  • 3
  • 7