Solving two consecutive dependent goals from command line

The path is given by db_attach/2, e.g.

db_attach('data.journal', [])

To keep the example simple it used the same directory as the code, e.g.

?- working_directory(_, 'C:/Users/Eric/Documents/Projects/Prolog/Persistence example/').
true.

Since db_path/2 can take a full path, you could also do something like

db_attach('C:/Users/Eric/Documents/Projects/Prolog/Persistence example/data.journal', [])

@jan Can you check this answer to make sure I am not giving very bad advise.

I would not. That warning is because I still don’t fully know the correct way to use library(persistency).

This also goes back to the statement I made in the explanation.

When writing to a file that can be open by multiple processes at the same time, the use of with_mutex/2 is probably required. However

entity(A).

is just trying to read the file and so no lock should be needed and thus with_mutex/2 should not be needed.

Since the with_mutex/2 is not needed, the predicate to read the facts, entity/1 which is in the facts module can be exported as is and the wrapper predicate exists_entity/1 can be removed. The changes to all three source code files becomes

program_a.pl

:- use_module('program_database.pl').

program_1 :-
    format('Starting saving ~n',[]),
    A = "a",
    B = "b",
    % Stuff
    %assert(entity(A)),
    (
        % exists_entity(A)
        entity(A)
    ;
        add_entity(A)
    ),
    %assert(entity(B)),
    (
        % exists_entity(B)
        entity(B)
    ;
        add_entity(B)
    ),
    % More stuff
    format('Done ~n',[]).

program_b.pl

:- use_module('program_database.pl').

program_2 :-
    format('Starting reading program ~n',[]),
    % Stuff
    write_entities.

write_entities :-
    % facts:entity(A),
    % exists_entity(A),
    entity(A),
    write_canonical(A),nl,
    fail.

program_database.pl

:- module(
    facts,
    [
      add_entity/1,          % +Identifier:string
      % exists_entity/1        % ?Identifier:string
      entity/1               % ?Identifier:string
    ]
  ).

:- use_module(library(persistency)).

:- persistent
    entity(identifier:string).

% :- initialization(db_attach('C:/Users/Eric/Documents/Projects/Prolog/Persistence example/data.journal', [])).
:- initialization(db_attach('data.journal', [])).

% exists_entity(Identifier):-
%   with_mutex(facts_journal, entity(Identifier)).

add_entity(Identifier):-
  with_mutex(facts_journal, assert_entity(Identifier)).

In other words what library(persistency) does is, that you give it a spec and it creates the 4 predicates

name(Arg, ...)
assert_name(Arg, ...)
retract_name(Arg, ...)
retractall_name(Arg, ...)

and you give it a file name, e.g. db_attach('data.journal', []) and it stores the clauses created by using assert_name(Arg, ...) into memory while the programming is running and a file when the program ends. I have not worked with the predicates such as db_detach/0, db_sync/1 and db_sync_all/1 so I can’t say more about them.

The rest is just code I added to make it more useful. It does not even need to be put into a separate module. However in the several cases I used it for and the case you used it for, it makes more sense as a module.


So you have library(persistency) working and know enough to now ask good questions, that pretty much puts you near to what I know about library(persistency), e.g. I only experimented for several hours when I asked the questions in Trying to understand library(persistency)

Thanks for asking the questions because it helps to reinforce/change my understanding of using library(persistency) and how others are using it and that some of the ways I explain it need more clarification. :smiley:

1 Like