You want to
write data to a file such that when you
eval that file that data is recreated.
Use the
pconvert library to convert data into a format, that when read, will recreate the data. For example, the
print-convert library converts data to quasi-quoted form:
> (require (lib "pconvert.ss"))
> (define data '(1 2 3 #(a b)))
> (print-convert data)
(quasiquote (1 2 3 #2(a b)))
> (eval (print-convert data))
(1 2 3 #2(a b))
> (equal? (eval (print-convert data)) data)
#t
> (eq? (eval (print-convert data)) data)
#f
Two convenience functions to write and read (eval) files are:
(define (write-converted data filename)
(with-output-to-file filename
(lambda ()
(write (print-convert data)))
'replace))
(define (read-converted filename)
(with-input-from-file filename
(lambda ()
(eval (read)))))
In use:
> (write-converted '(1 2 3 #(a b)) "test.txt")
> (read-converted "test.txt")
(1 2 3 #2(a b))
Note that
load can take the place of
read-converted in most situations.
Load will
eval all expressions in a file, while
read-converted will only
eval the first. In this way
read-converted is the mirror of
write-converted, which only writes a single expression to a file.
You might wonder we don't just use
write and
read instead of
print-convert. The range of data that can be represented by
print-convert is greater than that that can be represented by
write (is it really?). Additionally =print-convert=ed data can be intermingled with program code. This allows, for example, programmatic configuration files that are a mixture of code and print-converted data. This idea is sometimes known as an
Active File. For example:
> (eval `(map + ,(print-convert '(1 2 3)) ,(print-convert '(3 4 5))))
(4 6 8)
StructuresReadingAndWriting discusses reading and writing structures using
print-convert.
You might want to use
pretty-print instead of
write if you want it to be human-readable/editable.
--
DougOrleans - 22 Nov 2004
Just wondering - is "Active Files" a standard term?
And as a service for those searching the cookbook after "serialization", the
word is now mentioned.
--
JensAxelSoegaard - 27 Nov 2004
What if I edit the text file to say the following?
(for-each delete-file (directory-list))
--
DanielSilva - 9 Dec 2004
Jens - fair call. I've moved it to a more generic name
Daniel - I don't get your point. So you delete the file. What did you expect? We could (and should) talk about the funky stuff you can do with namespaces to sandbox code, but not in this recipe.
--
NoelWelsh - 09 Dec 2004
I just thought maybe it would be good to note in the discussion that something like
IdiomUntrustedEval? should be used instead of pure
eval for data files.
--
DanielSilva - 10 Dec 2004
--
NoelWelsh - 22 Nov 2004