Hi,
How can I create one or more prolog clauses using hook “prolog_load_files”?
According to the documentation, prolog_load_file/2 is used to
…deal with Prolog code that is not represented as a Prolog source text…
However, I could not find any documentation how to create the clauses I would need.
Example: I have the following file test.pl:
:- multifile mydata/1.
user:prolog_load_file(Spec, _Options) :-
strip_module(Spec, Mod, File)
, atom(File)
, file_name_extension(_Base, mydat, File)
, writeln(creating_clauses_from_file(Mod, File))
**% here we want to parse File and create facts in the form "mydata(a)."**
.
:- load_files('test.mydat').
Which I then call with “swipl test.pl”, with the following result:
*swipl test.pl*
**creating_clauses(user,test)**
Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?-
My question is: Once I have parsed my file, how can I add the resulting clauses to my program?
Thanks for any support
Thanks for this feedback.
I came across this example, too, but in the end, this one does nothing more than open an http-stream, then load_file from this stream…
Not really what I am looking for.
…
setup_call_cleanup(
http_open(FinalURL, In,
[ cert_verify_hook(ssl_verify)
]), load_files(Module:FinalURL, [stream(In)|Options]),
close(In)).
Before I try to answer your question, I need to ask something:
Is there a particular reason why you are writing text to a text file? Without understanding the issue you are solving, there are at least two other things you could try:
Directly use assertz/1 (also works with modules I think);
Use term_expansion/2.
From what I see (correct me if I am wrong) it seems that you are writing text to a file and then loading the contents as if it were Prolog code; this feels like an overkill for most use cases (and it will be not easy to debug either…)
That is completely up to you. Most of the implementations of this hook use it to get a handle to a stream containing Prolog source and than call load_files/2 using the stream(Input) option to do the actual loading. This is typically used to load code from (web)servers, databases, etc. You can do anything you want in the hook though.
You do not need this hook if your only problem is the file name extension. You can load any file containing Prolog code simply by adding the file name extension or use prolog_file_type/2 to define your extension as a valid alternative extension. There is an extensive example on tweaking input in library/dialect/xsb to read XSB’s .P files.
Well, my file does not contain prolog code at all. It has some structured data from an external source, that I can easily transform into prolog code.
So I could actually do the following:
read my external file “test.mydat”,
transform it into a corresponding prolog file eg: “test_mydat.pl”, and
load “test_mydat.pl” in my prolog application.
The problem with this approach is that I would have to update “test_mydat.pl” each time the underlying source would change.
But if I understand you well, 1 could do the following within my “prolog_load_file” hook:
read my external file “test.mydat”,
transform it into a corresponding prolog code and write this to some temporary file,
open the temporary file
and give this stream to load_files with the stream(In) option
I would have thought there is something less convoluted to add the clauses to the program but I will give this a try.
Thanks
That should work. You do not really need to create a file, you can also put it in a memory file or string and open that. You can also parse the data to clauses and assert them, but that skips all the source administration and thus makes reloading the modified original file less obvious. You probably also want to use the modified(Time) option when loading the temporary file.
Tested this approach, and is working well.
However, loading a bunch of files (using load_files with option expand(true)) seems very slow.
But anyway, thanks for your valuable input