Dealing with dynamic predicates that cause compilation failures - prolog

I am attempting to run an example GNU Prolog program used as an example during my course work. The code is pulled directly from https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_17pl.txt and was shown working at one point by my professor.
However, when I run the provided example code, I get the following compilation warning:
| ?- consult('C:/Users/Chase/Desktop/Prolog files/newAnimal.pro').
compiling C:/Users/Chase/Desktop/Prolog files/newAnimal.pro for byte code...
C:/Users/Chase/Desktop/Prolog files/newAnimal.pro:74:12: syntax error: . or operator expected after expression
1 error(s)
compilation failed
The line that is keeping the program from compiling correctly is:
:- dynamic yes/1,no/1.
Which I read up on here: https://www.swi-prolog.org/pldoc/man?predicate=dynamic/1
However, despite attempting to rewrite and reformat the section, I could still not get it to compile.
Any help on why the provided code may not be running?
I am using a Windows GUI GNU Prolog console V1.4.5

The ISO Prolog standard doesn't require dynamic(or multifile or discontiguous) to be declared as an operator. A few systems do it (e.g. SWI-Prolog like you mentioned) but not GNU Prolog. Thus, to ensure code portability, avoid using dynamic as an operator. Write instead:
:- dynamic(yes/1).
:- dynamic(no/1).
Or:
:- dynamic((yes/1, no/1)).
Or:
:- dynamic([yes/1, no/1]).
These are the standard conforming alternatives for declaring multiple predicates as dynamic.
Also, GNU Prolog have a fine manual (part of its installation) which you should refer to when using GNU Prolog.

Related

SWI-prolog semweb library processing of URI

Being new to prolog I am reading existing code (as well as trying to write some code). Having some prior background in semweb I started to play with it and see something that is confusing me. Example assertion:
?- rdf_assert(ex:bob, rdf:type, foaf:'Person').
I also did find the following in the documentation:
Remember: Internally, all resources are atoms. The transformations
above are realised at compile-time using rules for goal_expansion/2
provided by the rdf_db library
Am I correct in assuming that somehow the library is treating the three URIs as atoms? I thought that the compiler would treat this as module_name:predicate, but that does not seem to be the case. If that is true, could you please provide a simple example on how this could be done in prolog?
Thanks
Prolog is not a functional language. This implies 2+3 does not evaluate to 5 and is just a term that gets meaning from the predicate that processes it. Likewise, ex:bob is just a term that has no direct relations to modules or
predicates. Only predicates such call/1 will interpret this as "call bob in the module ex".
Next to that, (SWI-)Prolog (most Prolog's, but not all) have term expansion that allows you to rewrite the term that is read before it is handed to the compiler. That is used to rewrite the argument of rdf/3: each appearance of prefix:local is expanded to a full atom. You can check that by using listing/1 on predicates that call rdf/3 using the prefix notation.
See also rdf_meta

Workaround ensure_loaded/1 GNU Prolog?

Is there a workaround to make ensure_loaded/1 work
in GNU Prolog as it works in many other Prolog systems?
The goal is to have a preamble so that the rest of
code can use ensure_loaded/1 independent of whether which
Prolog system I use.
I tried the following:
:- multifile(term_expansion/2).
term_expansion((:- ensure_loaded(X)),
(:- atom_concat('<base>\\', X, Y),
include(Y))).
But the following query doesn't work:
:- ensure_loaded('suite.p').
The path calculation itself is not the issue of the question,
but the redefinition of a directive in GNU Prolog. There is
another directive that causes problems: meta_predicate/1. The
byte code crashes as follows:
Bye
A partial solution is:
ensure_loaded(File) :-
absolute_file_name(File, Path),
( predicate_property(_, prolog_file(Path)) ->
true
; consult(Path)
).
It assumes that the file defines at least one predicate but that's a sensible assumption. However, there's seems to be no way to override the native, non-functional, definition of the ensure_loaded/1 directive. A workaround would be to wrap the ensure_loaded/1 directive within an initialization/1 directive. For example:
:- initialization(ensure_loaded('suite.pl')).
Hence this being a partial solution as we're really defining an ensure_loaded/1 predicate, not a directive.
My current speculation is, that it is impossible with
the standard distribution of GNU Prolog 1.4.4. The
docu says:
The GNU Prolog compiler (section 4.4) automatically calls
expand_term/2 on each Term1 read in. However, in the current release,
only DCG transformation are done by the compiler (i.e.
term_expansion/2 cannot be used). To use term_expansion/2, it is
necessary to call expand_term/2 explicitly.
I also tried to inject some Prolog code for term_expansion/2
via the command line, but to no awail. Although the tool chain
has options such as -O, -L, -A that pass options to other tools.
There is not really an option that passes a Prolog text to the
pl2wam, in course of the execution of a consult/1 issued inside
the top-level.
At least this are my results so far.
Bye

Is there a way to use module/2 in ECLiPSe Prolog?

In SWI-Prolog, I am using code such as at the beginning
of a module text file:
:- module(foo, [bar/2]).
:- use_module(library(jack)).
I don't want to change my code. How can I neverthelss use
ECLiPSe Prolog (*). Is there some library that defines a
module/2 directive in ECLiPSe Prolog?
Best Regards
(*)
http://eclipseclp.org/
You can compile Prolog module that uses SWI-Prolog module system using Logtalk for use with ECLiPSe (or any other of the supported Prolog compilers, including those that don't provide a module system).
The following code defines a macro that maps module/2 into module/3 directives:
:- export macro((:-)/1, translate_directive/2, [top_only]).
translate_directive(
(:- module(Module, Exports)),
(:- module(Module, Exports, [swi]))
).
Compile (or import) this before compiling the module written for SWI. Note that the 3rd argument of module/3 must contain a language module, corresponding to the dialect your module is written in. I have used swi here, other choices would be quintus, iso or ECLiPSe's native eclipse_language.
No, there are only module/1 and module/3.
You an see the list of all what available here: http://eclipseclp.org/doc/bips/fullindex.html
SWI-Prolog (an others) module/2 directives can be replaced on ECLiPSe by module/1 + export/1 directives as you likely already found out. Also both SWI-Prolog and ECLiPSe support conditional compilation directives and the dialect flag. This should provide you with another alternative (not tested) for using the same Prolog files with both systems:
:- if(current_prolog_flag(dialect, swi)).
:- module(foo, [p/1]).
:- elif(current_prolog_flag(dialect, eclipse)).
:- module(foo).
:- export(p/1).
:- else.
...
:- endif.

How to turn Prolog into preprocessor (kinda m4, gpp)?

m4 can be used with different programming languages because its default policy on unrecognised text is to output and it has a quoting mechanism required for convenient preprocessor usage. I mean, I can write preprocessed code in such a way that my IDE thinks it's Ada. m4 macro invocations (include, define) are hidden in Ada comments. Ada comments start with --, Prolog comments start with % or inside /* */. I can't mix Ada and Prolog easily.
m4 does preprocessing well enough, but its programming side sucks. I thought: why don't me try a general purpose language instead? Prolog looks like being appropriate for my tasks. Prolog has ISO standard, and logic programming looks being useful for reasoning about source generation.
So here we are: we have an arbitrary output language (Ada, then JavaScript, then maybe something else), and it would be nice to write source code in native IDEs for corresponding languages most of the time. I need preprocessor to have a proper parser (like m4 has). This parser shouldn't have Ada syntax knowledge, instead it should only know Ada lexical, and it should be possible to make its macro invocations look like Ada functions invocations.
Its command line interface should look similar to m4 or gcc -E. It should be possible to do both kinds of includes: pure Prolog source code and preprocessed code.
If you know how can I shortly achieve these goals, please write here. I can probably accept non-Prolog solutions, but among the others I prefer standard languages. m4 is part of POSIX, for example.
Prolog is an unusual choice for this task. Indeed, SWI-Prolog used to have the possibility to invoke C preprocessor - should has been removed now, because of its little usefulness.
Anyway, a DCG could be used. I would advice against it if you are not really proficient in Prolog, because debugging can be difficult:
prep(I, O) :-
phrase(exp, I, O).
exp --> mac, !, exp.
exp, [C] --> [C], exp.
exp --> [].
% macro definitions, use 'pushback' argument to change text
mac, "AAA" --> "a".
mac, "G" --> "goal".
example
?- prep("my goal is mars", X).
X = "my G is mAAArs" .
edit: from SWI-Prolog mailing list, WRT the latest release 6.3.18
MODIFIED: Deleted preprocessor/2 after discussion on the
mailinglist. Code relying on this (we hope none) can use the hook
user:prolog_load_file/2 to achieve the same result.
I think the functionality available is more or less that of #include <...>.
For macro expansion (or better, term rewrite) in Prolog there is goal_expansion or term_expansion
edit: latest release brings quasiquotations. Together with a parser in DCG could help to achieve the transformation.
Have you looked at StringTemplate? It's a part of ANTLR (compiler construction toolket). It's written in Java (though there's a C# port, among others). An ANTLR grammar can be written to target many different languages. StringTemplate is what it uses to generate code for the different target languages.
Check it out.
http://antlr.org
http://stringtemplate.org
http://www.cs.usfca.edu/~parrt/
I use DCGs to generate python scripts for FontForge (to create and maintain candlestick fonts for forex trading); I tried M4 scripts but they are not easily amenable to programming (as you mention) and difficult to merge with my glyph definitions that reside in a Prolog database.
DCGs are perceived to be mainly for parsing; but I find they are like a templating engine on their own.

Saving GProlog database

In my program I have a dynamic clauses, they works fine, but when I closing my program, they are disappears.
I've tryed that
saveState :-
write_pl_state_file('backup.dat').
loadState :-
file_exists('backup.dat'),
read_pl_state_file('backup.dat'); !.
but this is not works.
Is there a way to save this databse to a file?
The predicates write_pl_state_file/1 and read_pl_state_file/1 are connected with the information/state that affects parsing of terms, i.e. operator definitions, character conversion Prolog flags, etc.
So that is part of your solution (perhaps), but more fundamentally you wish to save the dynamic clause definitions, probably in a form that allows you to reinstate them by consulting a file.
The predicate listing/0 does something like this, but it displays the dynamic clauses to the "console", not to a file. Probably you want to use the underlying predicate portray_clause/2, which does allow redirecting output to a file (stream).
The author Daniel Diaz noted a slight change (adding a newline to end of output) for portray_clause/2 in recent release notes for version 1.4.0, so you may want to make sure you've got the latest version for the sake of legibility.
Added:
It appears that starting with version 1.3.2 GNU Prolog supports sending listing/0 output to the current stream (rather than just to the console as in 1.3.1 and earlier).
Here's a test case:
| ?- assertz(whoami(i)).
| ?- assertz(whoami(me)).
| ?- assertz(whoami(myself)).
which creates three clauses (facts) for a dynamic predicate whoami/1.
I then created a file myClauses.pl with the following query:
| ?- open('myClauses.pl',write,S), set_output(S), listing, close(S).
Once the stream S is closed, current output is reset to the console.
You will find that the file myClauses.pl contains a blank line followed by the three clauses, so that the source code is in proper form to be consulted. However I'm having a problem with the consult/1 predicate (and its File -> Consult... menu equivalent) in my newly installed GNU Prolog 1.4.0 under Windows. The compilation works from the command line and produces a byte-code file that load/1 can correctly handle in the console, so there's some small problem in how things are set up. I'll post a further note when I get that squared away, having sent in a bug report. I've not tried it yet under Linux.
You can use current_predicate/1 or predicate_property/2 to access predicates, and clause/2 to access the clauses for a predicate.
Then you can write a save utility by using that information.

Resources