以下代码用于逐行显示读取的文本:
#!/usr/bin/env racket
#lang racket/base
(require racket/string)
(require racket/file)
(require racket/file)
(display "Line by line with for loop:nn")
(define f "../file-to-be-read.short")
(define content (file->lines f))
(for ([l content]) (display l))
(define (do-sth-to-each-line fn-name)
(define f "../file-to-be-read.short")
(define content (file->lines f))
(map fn-name content))
(display "nnAnd now line by line with map and display:nn")
(do-sth-to-each-line display)
代码从../file-to-be-read.short
读取,其内容为:
Not that I think you did not love your father,
But that I know love is begun by time,
And that I see, in passages of proof,
Time qualifies the spark and fire of it.
调用(do-sth-to-each-line display)
的结果如下:
Not that I think you did not love your father,But that I know love is begun by time,And that I see, in passages of proof,Time qualifies the spark and fire of it.'(#<void> #<void> #<void> #<void> #<void> #<void> #<void>)
'(#<void> #<void> #<void> #<void> #<void> #<void> #<void>)
来自哪里?为什么(for ([l content]) (display l))
不产生我意想不到的输出?
#<void>
是display
函数的返回值,因此'(#<void> #<void> #<void> #<void> #<void> #<void> #<void>)
是map
display
相对于content
的结果(map
和for
都生成结果列表,因此for
返回相同的结果)。
如果您想为列表中的每个元素运行一些副作用,您应该使用for-each
。
此外,不要在define
中使用define
,使用let
引入局部变量,并考虑使用displayln
:
#lang racket
(require racket/string)
(require racket/file)
(define (print-file filename)
(for-each displayln
(file->lines filename)))
(displayln "Now line by line with for-each and displayln:")
(print-file "../file-to-be-read.short")
使用for
的更好方法是:
(define (display-file filename)
(call-with-input-file filename
(lambda (port) (for ([line (in-lines port)]) (display line)))))
in-lines
返回一个序列,该序列一次迭代从端口读取的行,而不是先将整个文件读取到列表中,这使得它在大型输入文件上使用的内存要少得多。
还有display-lines
作为for-each
的替代品(正如Martin所指出的,它比这里的map
更好),尽管它也需要首先读取整个输入文件:
(display-lines (file->lines filename) #:separator #u200C)
它只显示给定列表中的每个元素,中间有一个分隔符(默认为#newline
,使其行为类似于每个元素的displayln
,而不是display
)。在这种情况下,为了模仿其他版本的行为,即不在行之间插入任何内容,U+200C ZERO WIDTH NON JOINER被用作分隔符,以在支持Unicode的程序中查看输出时获得相同的视觉效果。#space
是另一个选项,因为ZWNJ可能会对非ASCII文本造成意外影响(As可以而不是在行之间有分隔符)。