views:

55

answers:

2

I'm serializing data which may be an integer, an object (list) with other nested objects, and trying to make a choice as to what approach to be using. Of two, the first one is to create bytevectors recursively and copy them in the calling functions to a larger single bytevector; the second one is to use some kind of the stream I could write to. Eventually, notwithstanding the choice, I would be able to use the resulting binary array in any further processing which may happen to occur, e. g. I would compress the output data and send it via network or just write some parts of it to a file.

I'd like to stay functional enough (or completely) yet implementing the fast serializer. I'm using Racket, though any other Scheme implementation will also do.

Thank you.

UPDATE:

Following are the examples I've added after I found a solution so that users save some time searching the way as to how to write data :]

write-byte and write-bytes are of particular use when you need to write octets.

> (bytes? (with-output-to-bytes (lambda () (write-byte 42))))
#t
> (bytevector? (with-output-to-bytes (lambda () (write-byte 42))))
#t
> (bytevector->u8-list (with-output-to-bytes (lambda () (write-byte 42))))
{42}
> (bytes->list (with-output-to-bytes (lambda () (write-byte 42) (write-bytes (integer->integer-bytes #x101CA75 4 #f #t)))))
(42 1 1 202 117)
+1  A: 

Probably open-bytevector-output-port is what I'm looking for:

#lang scheme

(require rnrs/bytevectors-6)
(require rnrs/io/ports-6)

(define-values (oup ext-proc) (open-bytevector-output-port))
(write 4 oup)
(write 2 oup)
(ext-proc)
(make-bytevector 3 1)

Result:

Добро пожаловать в DrScheme, версия 4.2.5 [3m].
Язык: scheme; memory limit: 128 MB.
#"42"
#"\1\1\1"
> 
Yasir Arsanukaev
+2  A: 

You can use just write to write the data to a port. You can do that with all values, as a list that holds everything. It might need minor tweaking in case you have issues like cyclic data, where setting print-graph to #t will deal with it fine. And if you want the output to go to a byte string, then you can use open-output-bytes, or the convenient with-output-to-bytes function:

(with-output-to-bytes (lambda () (write (list value1 value2 value3))))

This is not going to be as compact as a binary representation -- but if you plan on compressing the output anyway, it doesn't matter much.

Eli Barzilay
@Eli: `with-output-to-bytes` and friends usually create an output port and call some proc [with that port as its one argument]. However — in case I'd use your approach — I'd like to be able to pass any other arguments to my custom proc as it's done in my current implementation http://paste.lisp.org/display/113007 (proc `write-any`).
Yasir Arsanukaev
No, `with-output-to-bytes` expects a *thunk* -- a function of no arguments. As for arguments, Scheme has lexical scope, and this function can use whatever names are bound.
Eli Barzilay
@Eli: I guess my function will no longer be a combinator if I go this way, since it would depend on variables unbound in its body, but which are bound outside of the latter.
Yasir Arsanukaev
(a) What's wrong with that? (b) Note that you can do *very* little if you use strict combinators -- even `+` is something that you get from the lexical environment. (And in Scheme, `lambda` is the same.)
Eli Barzilay