有许多手册如何在方案中输入,但我不明白如何使用它。 让我们说我们有简单的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)))))))
输出:
“()
如何保留列表的其余部分?
答案 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 '()))
=> '()