4

I have a prolog database file with lots of facts knowledge.pl. For example:

father_of(joe,paul).
father_of(joe,mary).
mother_of(jane,paul).
mother_of(jane,mary).
male(paul).
male(joe).
female(mary).
female(jane). % and so on.

This file is consulted (consult/1) every time my program is executed again.

I would like to be able to insert, modify and delete the facts I want (some of them directly, some others that meet some specific conditions) by writing or deleting directly within this database text file.

something like assertz, retract and retractall but modifying this text file so that the changes remain permanently there.

how can I do it?

mll
  • 195
  • 2
  • 13

2 Answers2

3

you can either create the facts you want and write them to the (same) file or modify the database and then save it in the file.

the difference is that with the first approach you will have the db of the old file loaded while the second approach will change it during execution.

From the way you phrased the question I assume that you want to do the second; to do this you should:

1)declare all the predicates that you want to change as dynamic 2)assert,retract etc during execution 3)write the new database to the file. you can use listing/1

To write you can do something like:

tell(knowledge),
.....
told.

or you can use some other io predicates. maybe using set_prolog_IO/3 would be the simplest way.

Now, if you wanted the first, you should construct the predicates (probably using the univ operator) or other string manipulation predicates and then write them to a file

EDIT:

there is listing/0 but that will list all the predicates loaded (something you might not want). after some searching I found source_file/2; so you can do something like

findall(X,source_file(X,FileName),L).

note that source_file/2 requires the absolute filename. you can use absolute_file_name/2 to get it the way source_file/2 formats the predicate is a bit weird (i was expecting something like foo/1) but it looks like you can give it to listing/1 and it works fine so you can do something like:

save(FileName):-
    absolute_file_name(FileName,Abs),
    findall(X,source_file(X,Abs),L),
    tell(FileName),
    maplist(listing,L),
    told.

on the other hand, you can always have a list with the predicates you want to store somewhere in the file

Thanos Tintinidis
  • 5,828
  • 1
  • 20
  • 31
  • having to do listing/1 of all the predicates is not ideal, but anyways it will work, thanks. Is there any way of doing something like listing but with an entire text file? Only for one specific file, not for all the loaded files in runtime. Just in case I have more than predicates in the file, like rules or module or library imports. – mll Jun 02 '12 at 08:59
3

If you are using SWI-Prolog there are several choices:

Searching for prolog persistence I stumped into persistency: a module that at first glance could be useful.

Then there is a library for 'external tables', i.e. stored in files and indexed. You should use that if you have data that doesn't fit in memory, or if loading/saving the entire data set takes too long.

Otherwise, the answer from thanosQR suggest the 'old fashioned' way to handle persistence.

CapelliC
  • 59,646
  • 5
  • 47
  • 90