Схема лукавства читала-читала мимо EOF
Используя guile 1.8 или guile 2, следующий код читает EOF, казалось бы, на несколько дополнительных строк, а затем останавливается. Эффект, который это оказывает в более крупной программе, частью которой является извлечение, состоит в том, что, по-видимому, происходит повреждение ранее прочитанных данных. Я неправильно использую read-line или тестирую eof-объект?
(use-modules (ice-9 rdelim))
(define f
(lambda (p)
(let loop ((line (read-line p)))
(format #t "line: ~a\n" line)
(if (not (eof-object? (peek-char p)))
(begin
(let ((m (string-match "^[ \t]*#" line)))
(if m
(begin
(format #t "comment: ~a\n" (match:string m))
(loop (read-line p))
)))
(format #t "read next line\n")
(loop (read-line p)))))))
(define main
(lambda ()
(let ((h (open-input-file "test")))
(f h))))
Вот минимальный образец входного файла:
1
2
3
# comment line
4
5
1
2
3
# comment line
4
5
1
2
3
# comment line
4
5
Это должно быть больше, чем несколько строк, чтобы проблема могла проявиться. Извиняюсь за длину примера кода, но проблема возникает только тогда, когда код достигает такой степени сложности (хотя и небольшой).
1 ответ
Я предлагаю переписать процедуру, это не кажется правильным способом прочитать файл и перебрать его строки. Примерьте вот это:
(define (f)
(let loop ((line (read-line)))
(if (not (eof-object? line))
(begin
(format #t "line: ~a\n" line)
(let ((m (string-match "^[ \t]*#" line)))
(if m (format #t "comment: ~a\n" line)))
(format #t "read next line\n")
(loop (read-line))))))
(define (main)
(with-input-from-file "test" f))
С вашим примером ввода, позвонив (main)
выводит на консоль следующий вывод, который, как мы надеемся, соответствует ожидаемому:
line: 1
read next line
line: 2
read next line
line: 3
read next line
line: # comment line
comment: # comment line
read next line
line: 4
read next line
line: 5
read next line
line: 1
read next line
line: 2
read next line
line: 3
read next line
line: # comment line
comment: # comment line
read next line
line: 4
read next line
line: 5
read next line
line: 1
read next line
line: 2
read next line
line: 3
read next line
line: # comment line
comment: # comment line
read next line
line: 4
read next line
line: 5
read next line