1

我正在尝试使用 Scheme(MIT/GNU Scheme 9.1),并且正在编写一些简单的程序来读写文件。

为了将文件中包含的所有行读入列表中,我编写了以下内容:

(define read-lines-from-port-impl
        (lambda (file-input-port)
                (let* ((line (read-line file-input-port))
                      )
                      (if (eof-object? line)
                          (list)
                          (cons line (read-lines-from-port-impl file-input-port))
                      )
                )
        )
)


(define read-lines-from-port
        (lambda (file-port)
                (if (input-port? file-port)
                    (read-lines-from-port-impl file-port)
                    (list)
                )
        )
)


(define read-lines-from-file
        (lambda (filename)
                (call-with-input-file filename read-lines-from-port)
        )
)

问题 1

这似乎可行,但在 Scheme 中可能有一种更惯用/更简洁的方法。你能建议如何改进这段代码吗?

问题2

在上面的代码中,我使用了 call-with-input-file,它负责在调用 read-lines-from-port 之前打开一个输入端口,并在该过程完成后关闭它。

如果我想使用 open-input-file 和 close-input-port 自己打开和关闭一个输入端口,我将如何在 Scheme 中编写它?我的意思是我必须

  • 调用打开输入文件
  • 从结果端口读取行
  • 调用关闭输入端口

在 Haskell 中,我会使用 do 表示法,但如何在 Scheme 中指定这样的一系列动作?

4

1 回答 1

2

我没有测试这段代码,但即使我出错了,你也应该能够从这里弄清楚:

; read-lines [port-or-filename] -- defaults to current input
(define (read-lines . args)
  (let ((p (cond ((null? args) (current-input-port))
                 ((port? (car args)) (car args))
                 ((string? (car args)) (open-input-file (car args)))
                 (else (error 'read-lines "bad argument")))))
    (let loop ((line (read-line p)) (lines (list)))
      (if (eof-object? line)
          (begin (if (and (pair? args) (string? (car args)))
                   (close-input-port p))
                 (reverse lines))
          (loop (read-line p) (cons line lines))))))

您使用 编写一系列语句begin,如上所示。

于 2012-07-03T21:21:38.777 回答