Как получить данные из библиотеки (постоянство) в SWI-Prolog?

#prolog #swi-prolog

#пролог #swi-prolog

Вопрос:

У меня есть этот модуль:

 :- module(data_db,
          [ attach_data_db/1,           %  File
            current_user_role/2,        % ?User, ?Role
            add_user/2,                 %  User,  Role
            set_user_role/2             %  User,  Role
          ]).
:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,administrator])).

attach_data_db(File) :-
        db_attach(File, []).

%%      current_user_role( Name, -Role) is semidet.

current_user_role(Name, Role) :-
        with_mutex(data_db, user_role(Name, Role)).

add_user(Name, Role) :-
        assert_user_role(Name, Role).

set_user_role(Name, Role) :-
        user_role(Name, Role), !.
set_user_role(Name, Role) :-
        with_mutex(data_db,
                   (  retractall_user_role(Name, _),
                      assert_user_role(Name, Role))).
  

Это пример из официальной документации. Итак, я могу добавлять данные в файл с db_attach помощью, но я не понимаю, как получить данные из файла. Файл содержит:

 created(1603178081.6254506).
assert(user_role('John',user)).
assert(user_role('John',user)).
assert(user_role(han,user)).
  

Комментарии:

1. @peter.cyc: нет причин удалять тег Prolog, так как он, хотя и специфичен для SWI, все еще связан с Prolog.

Ответ №1:

Сначала вам действительно следует задать этот вопрос на форуме SWI-Prolog, поскольку знание того, как использовать библиотеку (постоянство), известно не многим.

Одна из приятных особенностей library (persistency) заключается в том, что она управляет сохранением и загрузкой данных (фактов и предикатов) после правильной настройки.

Поскольку вы привели пример файла, созданного библиотекой (постоянство) Я буду считать, что у вас все работает правильно.

Ваша проблема та же, что и при первом использовании library (постоянство), поскольку я ожидал, что факты будут храниться в файле так же, как если бы я вводил их вручную. вручную. Это не то, как вы должны думать о библиотеке (постоянство), вместо этого думайте об этом как о создании журнала команд, и эти команды воспроизводятся при открытии журнала.

Поскольку это журнал команд, вот почему вы видите assert(user_role('John',user)). вместо user_role('John',user). . Команда утверждает факт в базе данных Prolog в памяти, когда файл открывается и воспроизводится библиотекой (постоянство), это делается автоматически библиотекой (постоянство).

Итак, чтобы ответить на ваш вопрос

Как получить данные из библиотеки (постоянство) в SWI-Prolog?

Просто получите доступ к фактам, как если бы они были в базе данных Prolog, например

 ?- user_role('John',Role).
Role = user.
  

Хотя создание Вики на форуме SWI-Prolog для использования библиотеки (постоянство) входит в мой длинный список, вот последний полный пост с рабочим кодом, который я написал.

Вам нужно будет нажать на треугольник, чтобы развернуть детали, чтобы увидеть код.


Вот полный рабочий пример, основанный на вашем вопросе. Существует два исходных файла Prolog, один используется для сохранения некоторых фактов в журнале, а затем остановки верхнего уровня Prolog, чтобы продемонстрировать, что данные передаются не через базу данных Prolog, а через файл журнала. Затем второй источник Prolog получит доступ к файлу журнала, делая факты доступными на верхнем уровне.

Файл: create_facts.pl

 :- module(create_facts,[]).

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,developer,administrator])).

:- db_attach('user.journal', []).

:- initialization(main).

add_user(Name, Role) :-
        (
                user_role(Name, Role), !
        ;
                assert_user_role(Name, Role)
        ).

main :-
    add_user('John',user),
    add_user('Mary',user),
    add_user('Ellen',developer),
    add_user('Stan',user),
    add_user('Eric',administrator).
  

Файл: load_facts.pl

 :- module(load_facts,[
                user_role/2
        ]).

:- use_module(library(persistency)).

:- persistent
        user_role(name:atom, role:oneof([user,developer,administrator])).

:- db_attach('user.journal', []).
  

Демонстрация

  1. Проконсультируйтесь create_facts.pl который автоматически запустит main создание фактов в файле журнала.
 ?- ['create_facts'].
true.
  
  1. остановите верхний уровень Prolog, чтобы показать, что факты передаются только в файле журнала. Кроме того, до тех пор, пока halt файл журнала не будет выполнен, он может быть неполным и по-прежнему будет заблокирован верхним уровнем SWI-Prolog.
 ?- halt.
  

Файл журнала, созданный на шаге 1

Файл: user.joural

 created(1603198849.086677).
assert(user_role('John',user)).
assert(user_role('Mary',user)).
assert(user_role('Ellen',developer)).
assert(user_role('Stan',user)).
assert(user_role('Eric',administrator)).
  

Если вы хотите, вы можете выполнять шаги 1 и 2 снова и снова, и это не будет дублировать факты в журнале, потому что

         (
                user_role(Name, Role), !
        ;
                assert_user_role(Name, Role)
        ).
  

проверьте, существует ли факт, и если нет, то подтвердите факт в журнале.

  1. Проконсультируйтесь load_facts.pl , чтобы загрузить факты из файла журнала в базу данных Prolog.
 ?- ['load_facts'].
true.
  
  1. Просто получите доступ к фактам, как если бы они были созданы обычным образом
 ?- user_role(Name,Role).
Name = 'John',
Role = user ;
Name = 'Mary',
Role = user ;
Name = 'Ellen',
Role = developer ;
Name = 'Stan',
Role = user ;
Name = 'Eric',
Role = administrator.
  

Наслаждайтесь!

Комментарии:

1. Я действительно ценю ваш ответ. Это помогло мне понять смысл использования persistency lib