[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [ANN] guile-msgpack: MessagePack for GNU Guile (+ help needed)
From: |
HiPhish |
Subject: |
Re: [ANN] guile-msgpack: MessagePack for GNU Guile (+ help needed) |
Date: |
Wed, 19 Sep 2018 16:06:48 +0200 |
Thompson, David wrote:
> So does this allow for sending over arbitrarily nested s-expressions
> (i.e. anything supported by Guile's 'read' and 'write' procedures)?
> For example:
>
> (pack '((foo . 1) (bar . (2 3 4)) (baz . "hello")))
Not quite, you are limited to the types MessagePack defines, because the
recipient might have no idea what types Guile has. Think of it like binary
JSON. However, the standard leaves room for your own extension via the `ext`
type. There is an example in the documentation:
(define (rational->ext x)
(make-ext 13
(pack (vector (numerator x)
(denominator x)))))
Let's say you want to pack an exact rational number while preserving its
exactness. There is nothing in the spec that supports such a type, so we will
chose to represent rational number as an extension with the number 13 (no
particular reason). An extension is a pair of a number and the data as a
bytevector. The simplest way to encode the numerator and denominator is to
pack a vector of the two numbers.
You can now pack this ext object and send it off through a port where on the
other end the recipient hopefully knows what to do with an extension object of
type 13:
(pack! (rational->ext 2/3) (current-output-port))
If you receive such an object it's easy to make a rational number from it
again:
(define (ext13->rational e)
;; The data gets unpacked as a vector of two numbers
(define numbers (unpack (ext-data e)))
;; The result is the quotient of those two numbers
(/ (vector-ref numbers 0)
(vector-ref numbers 1)))
If you don't want to go through this conversion ritual every time you can also
register rational numbers with the `packing-table` parameter. The manual goes
into more detail. But yes, with extension you could in principle pack an
expression like ` '((foo . 1) (bar . (2 3 4)) (baz . "hello"))`, you would
just have to first define *how* to pack pairs. Symbols are currently packed as
strings, but that can be overridden as well.
> Guile doesn't provide any static type system. I haven't looked at your
> source, but when you say "a pair", do you mean a literal cons cell?
> If so, I recommend switching to record types via the (srfi srfi-9)
> module. You can write a custom constructor that does the type checks
> if you'd like.
I already use SRFI 9 (define-record-type) to generate everything, an `ext` is
a record with two slots. I'll look into it again then, seems like I missed
that part.
> You could resolve this by changing 'pack' to only accept a single
> value. If the user wants to pack multiple items, then they would pass
> a list or vector.
MessagePack already defines arrays (vectors), so packing a vector of three
objects and packing three objects is not the same.