As I get more familiar with Gambit, I find it's notion of ports to be really really useful. However, I don't know how to create these structures myself. Can someone point me to some sample code? A really great example would be something like:
(define-type tagged-data tag data)
then, as a piece of data is written to the output port, it's tagged with a (increasing number), and when it's read off the input port, it's a piece of tagged data
so ssuppose I wrote 'a 'b 'c 'd 'e to the port
then when I read from it, I get back
(make-tagged-data 1 'a) (make-tagged-data 2 'b) ... (make-tagged-data 5 'e)
The point of this isn't this particular problem, but to understand what abstractions I need to provide when writing my own ports.
Thanks!
Afficher les réponses par date
On 21-Jun-09, at 11:13 PM, lowly coder wrote:
As I get more familiar with Gambit, I find it's notion of ports to be really really useful. However, I don't know how to create these structures myself. Can someone point me to some sample code? A really great example would be something like:
(define-type tagged-data tag data)
then, as a piece of data is written to the output port, it's tagged with a (increasing number), and when it's read off the input port, it's a piece of tagged data
so ssuppose I wrote 'a 'b 'c 'd 'e to the port
then when I read from it, I get back
(make-tagged-data 1 'a) (make-tagged-data 2 'b) ... (make-tagged-data 5 'e)
The point of this isn't this particular problem, but to understand what abstractions I need to provide when writing my own ports.
#|
The low-level port data structure is not made public because it has a non-trivial interface which involves other non-trivial interfaces (readtables, read environments, write environments, port locks, etc).
However, by using pipes it is possible to implement fancy encoders and decoders for the data that is transferred on the port. The basic idea is to wrap the underlying port with a pipe, and create a thread which transfers the data between the port and the pipe doing any encoding/decoding that is needed.
Here's an example which adds a sequence number to each object that is written with the "write" procedure.
|#
(define (open-output-file-seq path-or-settings) (receive (in out) (open-vector-pipe '(direction: input)) (let* ((port (open-output-file path-or-settings)) (pump (make-thread (lambda () (let loop ((seqnum 0)) (let ((x (read in))) (if (not (eof-object? x)) (let ((tagged (vector seqnum x))) (write tagged port) (newline port) (force-output port) (loop (+ seqnum 1))) (close-port port)))))))) (thread-start! pump) (##add-exit-job! ;; make sure pump is done when we exit (lambda () (close-port out) (thread-join! pump))) out)))
(define p (open-output-file-seq "test-seq.txt"))
(write 'hello p)
(write 'world p)
(close-port p)
#|
The file test-seq.txt will contain:
#(0 hello) #(1 world)
|#
Marc