如何从输入文件

时间:2018-03-30 03:08:32

标签: io scheme racket

有许多手册如何在方案中输入,但我不明白如何使用它。 让我们说我们有简单的txt文件作为输入 A.TXT:

  

1 2 3

我正在调用标准的io程序

(let ((p (open-input-file "a.txt")))
  (let f ((x (read p))) ; reading from file
    (if (eof-object? x) ; check for eof
    (begin
      (close-input-port p)
      '()
      )
   (cons x (f (read p))))))

输出:

  

'(1 2 3)

这是我正在寻找的东西,但是如果我想对它进行标准的对/列表操作,我就得不到我的期望:

(let ((p (open-input-file "a.txt")))
  (let f ((x (read p))) ; reading from file
    (if (eof-object? x) ; check for eof
    (begin
      (close-input-port p)
      '()
      )
   (cdr 
      (cons x (f (read p)))))))

输出:

  

“()

如何保留列表的其余部分?

1 个答案:

答案 0 :(得分:2)

请注意,您要操作的列表由(let ...)表达式构成,即:

(let ((p ...)) ...)                       ;; => '(1 2 3)

所以,为了得到"休息"在列表中,您必须将cdr应用于整个let表达式,即:

(cdr (let ((p ...)) ...))                 ;; => '(2 3)

在let表达式之外应用cdr而不是在within之内是有区别的。当你在外面应用它时,let表达式首先被计算到一个列表,然后cdr进行操作以得到它的"休息"值。这相当于写作:

(cdr '(1 2 3))                            ;; => '(2 3)

但是如果你按照它在身体中的方式应用它,那么在f的每次递归调用中,这是递归到列表的单个cons单元格,所以到目前为止,你最终将cdr链接到它,所以不是按如下方式构建一系列缺点:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)

你改为构造一个形式的链:

(cdr (cons 1 (cdr (cons 2 (cdr (cons 3 '()))))))          ;; => '()

要了解这种情况如何发生,最好是从心理上思考或记下程序的执行流程。这使您可以了解表达式将评估的内容。

例如,您的第一个let表达式可以重写为等效函数,如下所示:

(define p (open-input-file "a.txt"))

;; (let f (...) ...) is a named let,
;; and is equivalent to the function below.
(define (f x)
  (if (eof-object? x)
      '()
      (cons x (f (read p)))))

(f (read p))

(close-input-port p)

并且其执行流程看起来如下:

(f (read p))
=> (f 1)
=> (cons 1 (f (read p)))
=> (cons 1 (f 2))
=> (cons 1 (cons 2 (f (read p))))
=> (cons 1 (cons 2 (f 3)))
=> (cons 1 (cons 2 (cons 3 (f (read p)))))
=> (cons 1 (cons 2 (cons 3 (f eof))))
=> (cons 1 (cons 2 (cons 3 '())))    ;; => '(1 2 3)

但如果您将cdr应用于递归调用,请按以下步骤操作:

(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))

然后执行将更改为以下内容:

(f (read p))
=> (f 1)
=> (cdr (cons 1 (f (read p))))
=> (cdr (cons 1 (f 2)))
=> (cdr (cons 1 (cdr (cons 2 (f (read p))))))
=> (cdr (cons 1 (cdr (cons 2 (f 3)))))
=> (cdr (cons 1 (cdr (cons 2 (cdr (cons 3 (f (read p))))))))
=> (cdr (cons 1 (cdr (cons 2 (cdr (cons 3 (f eof)))))))
=> (cdr (cons 1 (cdr (cons 2 (cdr (cons 3 '()))))))
=> (cdr (cons 1 (cdr (cons 2 '()))))
=> (cdr (cons 1 '()))
=> '()