segunda-feira, 19 de maio de 2014

PL Framework

Glider
Falei sobre como gerenciar dados mutáveis em Prolog. O código final ficou assim:


-*- Prolog -*-
:- module(profile, [profile/2]).
:- dynamic profile/2.

set(ID, X) :- profile(ID, X), !.
set(ID, X) :- X =.. [Attr, _],
              E =.. [Attr, _],
              retractall(profile(ID, E)),
              assertz(profile(ID, X)), !.

set(_, []) :- !.
set(ID, [X|Rest]) :- set(ID, X), set(ID, Rest).

get(ID, R) :- findall(X, profile(ID, X), R).

drop(ID) :- retractall(profile(ID, _)).

Mas e se quisermos que os dados sejam persistentes, ou seja, sobrevivam entre execuções, como um banco de dados?

O dialeto SWI Prolog oferece um arcabouço com inúmeros recursos chamado PL Framework.

Para persistência, há a biblioteca persistency.pl.

O que temos de fazer é substituir algumas partes de nosso código pelos predicados da biblioteca. Começaremos importando o módulo: logo após a declaração do nosso módulo, na linha abaixo, acrescente a importação:
:- use_module(library(persistency)).

Em seguida, não precisamos mais declarar o predicado profile/2 como dinâmico, em vez disso vamos declarar uma persistência. Substituia a linha com dynamic por:
:- persistent profile(id:atom, attr:compound).

Agora precisamos subtituir as chamadas de retractall/1 por retractall_profile/2, protegidas por with_mutex/2.

Onde está:
              retractall(profile(ID, E)),

Substitua por:
              with_mutex(profile,
                         retractall_profile(ID, E)),

E substitua:
drop(ID) :- retractall(profile(ID, _)).

Por:
drop(ID) :- with_mutex(profile,
                       retractall_profile(ID, _)).

Agora precisamos substituir assertz/1 por assert_profile/2. Onde está:
              assertz(profile(ID, X)), !.

Substitua por:
              with_mutex(profile, 
                         assert_profile(ID, X)), !.

Você pode juntar os predicados dentro de with_mutex/2.

Precisamos agora de uma regra para conectar a uma base de dados em disco, por exemplo:
connect(File) :- db_attach(File, [gc]).

Se quiser um arquivo padrão:
connect :- connect('profile.db').

Código final com persistência

-*- Prolog -*-
:- module(profile, [profile/2]).
:- persistent profile(id:atom, attr:compound).

set(ID, X) :- profile(ID, X), !.
set(ID, X) :- X =.. [Attr, _],
              E =.. [Attr, _],
              with_mutex(profile,
                         (retractall_profile(ID, E),
                          assert_profile(ID, X))), !.

set(_, []) :- !.
set(ID, [X|Rest]) :- set(ID, X), set(ID, Rest).

get(ID, R) :- findall(X, profile(ID, X), R).

drop(ID) :- with_mutex(profile,
                       retractall_profile(ID, _)).

connect :- connect('profile.db').

connect(File) :- db_attach(File, [gc]).

Este artigo foi apenas um exemplo prático de Prolog.

[]’s
ℭacilhας, ℒa ℬatalema
blog comments powered by Disqus