Чтение строки Guile Scheme после EOF

Используя guile 1.8 или guile 2, следующий код читает за EOF, по-видимому, несколько дополнительных строк, а затем останавливается. Эффект, который это имеет в более крупной программе, из которой это является извлечением, состоит в том, чтобы, по-видимому, повредить ранее считанные данные. Я неправильно использую строку чтения или тестирую объект 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

Чтобы проблема проявилась, она должна быть больше нескольких строк. Приносим извинения за длину примера кода, но проблема возникает только тогда, когда код достигает такой степени сложности (хотя и небольшой).


person andro    schedule 21.05.2017    source источник
comment
Основная проблема, по-видимому, заключается в том, что вы читаете две строки за итерацию, когда находите комментарий, см. мой ответ, чтобы узнать о другом способе структурирования решения.   -  person Óscar López    schedule 21.05.2017


Ответы (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
person Óscar López    schedule 21.05.2017
comment
Как ни странно, в Guile 1.8 нет случаев когда и если. Конечно, их можно написать или использовать альтернативную логику. - person andro; 22.05.2017
comment
@andro Я этого не знал. Вот, исправили. Кроме этого, это сработало для вас? - person Óscar López; 22.05.2017
comment
Этот фрагмент работает нормально. Но проблема кажется более тонкой. Что я делаю, так это пишу небольшой синтаксический анализатор, который проверяет строки на совпадения с шаблоном, выполняет некоторые вычисления для совпадения, а затем я хочу получить следующую строку, что я пытаюсь сделать, снова вызвав цикл со значением цикла, предоставленным чтение ввода с помощью строки чтения. Другими словами, своего рода «следующая» контрольная форма. Когда я добавляю много таких утверждений, схема ведет себя непредсказуемым образом. Неужели нельзя таким образом выйти из цикла и вернуться к следующей итерации? - person andro; 22.05.2017
comment
Трудно угадать, что вам на самом деле нужно. В Схеме нет следующего, но вы говорите так, как будто если/иначе было бы достаточно. Если есть совпадение, обработайте его, иначе ничего не делайте - и в любом случае перейдите к следующей строке. - person Óscar López; 22.05.2017
comment
Я почти уверен, что тем, что вам нужно, можно управлять с помощью стандартных операций потока управления и рекурсии, но без дополнительного контекста это невозможно сказать. На данный момент я думаю, что на ваш первоначальный вопрос был дан ответ. Если у вас возникнут дополнительные трудности, рассмотрите возможность публикации нового вопроса. ИМХО мой ответ уже приемлем;) - person Óscar López; 22.05.2017