在Racket中

时间:2018-01-29 09:48:09

标签: port racket

在Racket中,我希望能够窥视端口中的任何位置(也在当前位置之前),并在那里读取内容,而不会以任何方式影响端口。指定的位置(以下代码中的start-pos)应该是从头开始,而不是相对于当前端口位置!

我的第一次尝试:

(define (extract-string port start-pos span)
  (define pos (file-position port))
  (file-position port start-pos)
  (define result (read-string span port))
  (file-position port pos)
  result)

(define port (open-input-string "Hello world"))
(port-count-lines! port)
(port-next-location port)
(extract-string port 0 3)
(port-next-location port)

输出:

1
0
1
"Hel"
1
3
4

以某种方式,(file-position port pos) ...

未重置该职位

我的第二次尝试:

(define (extract-string port start-pos span)
  (define port2 (peeking-input-port port #:init-position start-pos))
  (read-string span port2))

(define port (open-input-string "Hello world"))
(port-count-lines! port)

; port-next-location is not affected; great
(port-next-location port)
(extract-string port 1 3)
(port-next-location port)

; Reading from an earlier point does not work!
(read-string 6 port)
(extract-string port 1 3)
(read-string 5 port)

输出:

1
0
1
"Hel"
1
0
1
"Hello "
"wor"
"world"

编辑:预期输出:

1
0
1
"Hel"
1
0
1
"Hello "
"Hel"
"world"

一个小的改进,但它仍然没有按预期工作..出于某种原因,port2的初始位置偏离port的初始位置,尽管参考文献

  

结果端口的初始位置(由文件位置报告)   是( - 初始位置1),无论是否位于。

在Racket中不可能这样做吗?

1 个答案:

答案 0 :(得分:1)

评论后修改:

(define port (open-input-string "Hello world"))

(define (extract-string-getter my_port)
  (let* ((prev_pos (file-position my_port))
         (new_port (open-input-string (port->string my_port))))
    (file-position my_port prev_pos)
    (lambda (start_pos span)
      (peek-string span start_pos new_port))
    ))

(define runner (extract-string-getter port))
runner
(runner 1 3)
(runner 1 3)
;(runner 5 9)
(port-count-lines! port)
; port-next-location is not affected; great
(port-next-location port)
;(extract-string port 1 3)
(port-next-location port)

; Reading from an earlier point does not work!
(read-string 6 port)
(runner 0 2)
(read-string 5 port)
(runner 6 9)

您仍然存在范围问题:)了解范围内外非常重要。

内部lambda有一个状态,通过保存对它的引用,'reader',我能够重用它的内部对象的状态!

<强>输出:

#<procedure:...\Documents\1.rkt:18:4>
"ell"
"ell"
1
0
1
1
0
1
"Hello "
"He"
"world"
"world"

重要事项:

  • 最好为 extract-string 的参数端口设置一个名称,而不是全局参数端口的名称。
  • 我创建了一个新端口,以便不妨碍原始端口,然后读取所有内容并重置文件位置(尽管我确定有一种更漂亮的方式)。
  • 当您想要封装时使用lambdas作为对象