[gambit-list] problem with serialization/deserialization of structures
Marc Feeley
feeley at iro.umontreal.ca
Mon Nov 27 23:38:44 EST 2006
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 27-Nov-06, at 3:45 PM, Alexey Voinov wrote:
>
> Hello.
>
> A friend of mine recently discovered strange behavior in gambit
> interpreter:
>
> $ gsi
> Gambit Version 4.0 beta 20
>
>> (define-structure foo x y)
>> (define a (make-foo 11 22))
>> a
> #<foo #2 x: 11 y: 22>
>> (foo? a)
> #t
>> (define b (u8vector->object (object->u8vector a)))
>> b
> #<foo #3 x: 11 y: 22>
>> (foo? b)
> #f
>> (define c (u8vector->object (object->u8vector a)))
>> c
> #<foo #4 x: 11 y: 22>
>> (foo? c)
> #f
>> (##vector-ref a 0)
> #<type #5 foo>
>> (##vector-ref b 0)
> #<type #6 foo>
>> (##vector-ref c 0)
> #<type #7 foo>
>>
>
> Note, now we have three different types named foo, but can do anything
> useful only with one of them.
This is not a bug, it is a feature. Let me explain with this
slightly different example:
(define-structure foo
x
y)
(define a (make-foo 11 22))
(with-output-to-file "data"
(lambda () (write (object->u8vector a))))
(define b (u8vector->object
(with-input-from-file "data" read)))
(pp (equal? a b)) ==> #f
This code creates an instance of the "foo" record type (i.e. "a"),
writes a serialized representation to a file, and reads it back as
the object "b".
A very similar scenario is having a Scheme program X write "a" to a
file, and having a *different* Scheme program Y read the file to
create the object "b" (or a process X might send "a" to a process Y
over the network). How can Y determine that the type it calls "foo"
is the same as the type called "foo" in X? It is important to
address this issue because we want the system to guarantee that
operations applied to the incorrect type yield an error.
One possible approach is to say that two record types are the same if
they have the same name. This is a poor approach because two record
types may have the same name by coincidence yet have different
fields, because they are defined in completely unrelated modules
(perhaps by different programmers). Another approach is to say that
two record types are the same if they have the same name, the same
number of fields, with the same names. This is more robust, but it
fails when say two programmers have chosen the same names and fields
for completely unrelated purposes (this is more likely when the
structure is really simple, like a record named "foo" with two fields
"x" and "y", is the type a 2D point, or the dimensions of a 2D
matrix, or a dotted pair, or ...?). Gambit errs on the side of
safety by treating the types foo in X and Y as different, even if
they have the same names and fields.
Communication of record types between programs (or between a program
and a database and back, etc) is achieved in Gambit by having the
programmer identify explicitly which type he is denoting by giving it
a "globally" unique name, different from the programmatic name. The
type identifier can be any symbol, but generally it is generated by a
tool like "uuidgen", which is basically a 128 bit random number
generator. Here's how you would change the record type definition:
(define-structure foo
id: foo-6BE0B751-0408-460A-B63A-9A96A843A88E
x
y)
With this the program returns #t. If two programs X and Y need to
exchange records of this type, they will each contain that record
definition.
Marc
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (Darwin)
iD8DBQFFa71V//V9Zc2T/v4RArnsAJ95HeDEF2JPPxeLLpGVTzz7bOBcLwCcCHJ1
c2ZTmXKUhk0dfWrIoEaN6ls=
=EQmV
-----END PGP SIGNATURE-----
More information about the Gambit-list
mailing list