quinta-feira, 12 de junho de 2008

Persistência de dados (e código!) em Scheme

Hoje eu e o Vilson estávamos conversando sobre persistência de dados (e código!) em Lisp. Fiz um exemplo simples e estou colocando abaixo para não perder a viagem. :-)

O exemplo implementa um objeto mem (criado com o procedimento make-mem) e procedimentos para manipulação desse tipo de objeto: mem-get (para leitura de dados) e mem-set! (para escrita em memória e em disco).

A leitura de dados é sempre feita da memória (exceto na criação do objeto, que pode aproveitar dados do arquivo passado como argumento). As escritas são feitas em memória e em disco.

Os dados são armazenados em uma hash-table e indexados por símbolos.

Abaixo está a implementação simplificada (em Chicken Scheme), que usa o egg s11n:

(use s11n)

(define (make-mem file)
(cons file (if (file-exists? file)
(with-input-from-file
file
(cut deserialize))
(make-hash-table))))

(define (mem-get mem key #!optional default)
(hash-table-ref/default (cdr mem) key default))

(define (mem-set! mem key val)
(let ((file (car mem))
(data (cdr mem)))
(hash-table-set! data key val)
(with-output-to-file file (cut serialize data))))

A seguir está um exemplo que armazena uma lista e um procedimento (código!):

(let ((mem (make-mem "teste.data")))
(print (mem-get mem 'a))
(mem-set! mem 'a '(1 2 3))
(print (mem-get mem 'a))
(mem-set! mem 'soma (lambda (a b) (+ a b)))
(print ((mem-get mem 'soma) 2 2)))

O resultado da execução do código do exemplo é (caso em que teste.data inicialmente não existe):


#f
(1 2 3)
4

Nenhum comentário: