Io 如何从输入文件中引用列表

Io 如何从输入文件中引用列表,io,scheme,racket,Io,Scheme,Racket,有很多关于如何在scheme中输入的手册,但我不知道如何使用它。 假设我们有一个简单的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) '()

有很多关于如何在scheme中输入的手册,但我不知道如何使用它。 假设我们有一个简单的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)))))))
输出:

“()


如何获取列表的其余部分?

请注意,要操作的列表是由
(let…
表达式构建的,即:

(let ((p ...)) ...)                       ;; => '(1 2 3)
(cdr (let ((p ...)) ...))                 ;; => '(2 3)
因此,要获得列表的“其余部分”,必须对整个let表达式应用
cdr
,即:

(let ((p ...)) ...)                       ;; => '(1 2 3)
(cdr (let ((p ...)) ...))                 ;; => '(2 3)
在let表达式外部应用
cdr
与在内部应用不同。当您在外部应用它时,let表达式首先被计算为一个列表,该列表
cdr
然后进行操作以获取其“rest”值。这相当于写:

(cdr '(1 2 3))                            ;; => '(2 3)
但是如果你在它的主体中应用它,那么在每次递归调用
f
时,其中一个
cons
单元格被递归地追加到列表中,你最终会将一个
cdr
链接到它,而不是像下面那样构建一个cons链:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))
而是构建一个表单链:

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

要了解这是如何发生的,最好从思想上考虑或写下程序的执行流程。这使您能够理解表达式的计算结果

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

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))
它的执行流程如下所示:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))
但是如果您将
cdr
应用于递归调用,如下所示:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(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 '()))
=> '()

请注意,要操作的列表是由
(let…
表达式构造的,即:

(let ((p ...)) ...)                       ;; => '(1 2 3)
(cdr (let ((p ...)) ...))                 ;; => '(2 3)
因此,要获得列表的“其余部分”,必须对整个let表达式应用
cdr
,即:

(let ((p ...)) ...)                       ;; => '(1 2 3)
(cdr (let ((p ...)) ...))                 ;; => '(2 3)
在let表达式外部应用
cdr
与在内部应用不同。当您在外部应用它时,let表达式首先被计算为一个列表,该列表
cdr
然后进行操作以获取其“rest”值。这相当于写:

(cdr '(1 2 3))                            ;; => '(2 3)
但是如果你在它的主体中应用它,那么在每次递归调用
f
时,其中一个
cons
单元格被递归地追加到列表中,你最终会将一个
cdr
链接到它,而不是像下面那样构建一个cons链:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))
而是构建一个表单链:

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

要了解这是如何发生的,最好从思想上考虑或写下程序的执行流程。这使您能够理解表达式的计算结果

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

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))
它的执行流程如下所示:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(define (f x)
  (if (eof-object? x)
      '()
      (cdr (cons x (f (read p))))))
但是如果您将
cdr
应用于递归调用,如下所示:

(cons 1 (cons 2 (cons 3 '())))                            ;; => '(1 2 3)
(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)
(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 '()))
=> '()

太多了!我需要它就行了。只是一个简单的问题。为什么我不能在let中以同样的方式进行cdr?无论如何,我都会将其分配给p。@Adam查看我上面的编辑,以了解为什么在计算列表的表达式之外应用
cdr
与在其主体内应用
cdr
不同。谢谢!我需要它就行了。只是一个简单的问题。为什么我不能在let中以同样的方式进行cdr?无论如何,我都会将其分配给p。@Adam请参阅我上面的编辑,以了解为什么在对列表求值的表达式外部应用
cdr
与在其主体中应用
cdr
不同。