我建议定义一个简单的辅助功能,make-codec-input-port
,让您从原始输入端口和一个“编解码器”功能创建一个输入端口。这里的关键点 - 对于我来说,make-pipe
的Racket文档不是很明显 - 您想要运行调用编解码器功能的thread
。
在这里我展示了一个普通的编解码器,它可以用#\b
替代每个#\a
字符。你可以改变它的match
声明来做更有趣的事情。
#lang racket
;; Given an input-port and a codec function, return a new input-port
;; that is the encoded version. `codec` is (input-port? output-port?
;; -> any). For example can be deflate, inflate, gzip-through-ports,
;; gunzip-through-ports, copy-port (the identity function for this),
;; or your own such function.
(define codec-buffer-size (make-parameter 1024))
(define (make-codec-input-port in codec [name #f])
(define-values (pin pout) (make-pipe (codec-buffer-size) name name))
(thread (lambda()
(codec in pout)
(close-output-port pout)))
pin)
;; Example of a codec function.
(define (replace-a-with-b in out) ;; (input-port? output-port? -> any)
(let loop()
(define ch (read-char in))
(unless (eof-object? ch)
(write-char (match ch
[#\a #\b]
[x x])
out)
(loop))))
;; You could also write the codec function a bit more simply using
;; `in-port`:
(define (replace-a-with-b in out) ;; (input-port? output-port? -> any)
(for ([ch (in-port read-char in)])
(write-char (match ch
[#\a #\b]
[x x])
out)))
;; Example direct use of the codec function.
(let()
(define orig-in (open-input-string "axaxax"))
(replace-a-with-b orig-in (current-output-port)))
;; => bxbxbx
;; Example use of the encoded input port. With this, a user of the
;; port need not know anything about the codec function.
(let()
(define orig-in (open-input-string "axaxax"))
(define encoded-in (make-codec-input-port orig-in replace-a-with-b))
(port->string encoded-in))
;; => "bxbxbx"
通常'make-pipe'是你不想写定制端口的东西,而且'make-pipe'通常要容易得多。你能用一些示例代码更新你的问题吗?你尝试过的东西,但不适合你? –
@GregHendershott我已经添加了一些我正在尝试的代码 – JNevens