[gambit-list] How to save s-expressions

Marc Feeley feeley at iro.umontreal.ca
Mon Oct 29 10:54:06 EDT 2012


Le 2012-10-27 à 8:44 AM, Marc Feeley <feeley at iro.umontreal.ca> a écrit :

> 
> Le 2012-10-27 à 4:31 AM, Richard Prescott <rdprescott at gmail.com> a écrit :
> 
>> Good morning everybody,
>> 
>> Forgive my ignorance, I am just learning.
>> 
>> In order to embrace the "code is data" philosophy [1], I want to load and save data as s-expressions within files.  I figured the load using (read (open-input-file "data.scm")).
>> 
>> How can I save?
>> 
>> Thanks in advance.
>> 
>> Richard
> 
> While it does work, your code does not close the input-port and relies on the garbage collector to do this, which is a bad idea (because you may run out of file descriptors before a garbage collection is triggered).  It is better to use call-with-input-file which closes the port.
> 
> Here are better save and restore functions:
> 
> ;; File: save-restore.scm
> 
> (define (save-to-file filename obj)
>  (call-with-output-file
>    filename
>    (lambda (port) (write obj port))))
> 
> (define (restore-from-file filename)
>  (call-with-input-file
>    filename
>    (lambda (port) (read port))))
> 
> (save-to-file "data.txt" '#(1 2 3))
> 
> (pp (restore-from-file "data.txt"))
> 
> 
> Marc


Here's an improved version of those functions which allows any serializable object, including functions, to be saved/restored.  The code uses the functions object->u8vector and u8vector->object which encode/decode any object to/from a vector of bytes.  In the case of interpreted functions, the source code locations are saved in the encoding (so that any error in a restored function will give an error message which points to the correct source code location).  See the example below.

Marc

;; File: save-restore.scm

(define (write-file filename obj)
  (call-with-output-file
    filename
    (lambda (port) (write obj port))))

(define (read-file filename)
  (call-with-input-file
    filename
    (lambda (port) (read port))))

(define (save-to-file filename obj)
  (write-file filename (object->u8vector obj)))

(define (restore-from-file filename)
  (u8vector->object (read-file filename)))

;; test it

(save-to-file "code.txt" (lambda (x) (/ 1.0 (* x x))))

(define inverse-square (restore-from-file "code.txt"))

(pp (inverse-square 10))

(pp (inverse-square "foo"))

;; gives:
;;
;; .01
;; *** ERROR IN inverse-square, "save-restore.scm"@21.45 -- (Argument 1) NUMBER expected
;; (* "foo" "foo")




More information about the Gambit-list mailing list