Чтение Common Lisp из файла и сохранение в виде списка

Итак, выполняя некоторые обычные упражнения на шепелявость, все шло хорошо, пока я не столкнулся с этим странным поведением. Я читаю текст из файла (brown.txt) в переменную corpus, и он должен храниться в виде списка. Однако я подозреваю, что это не так, хотя иногда он работает как один, а в другое время терпит неудачу.

Вот базовое чтение из файла -> добавление для списка -> сохранение списка в материале corpus (разделено/размечено пробелами):

(defun tokenize (string)
  (loop
     for start = 0 then (+ space 1)
     for space = (position #\space string :start start)
     for token = (subseq string start space)
     unless (string= token "") collect token
     until (not space)))

(defparameter *corpus*
   (with-open-file (stream "./brown.txt" :direction :input)
     (loop for line = (read-line stream nil)
           while line
           append (tokenize line))))

И ниже приведены 2 выражения, которые оба должны работать, но работает только последнее (корпусное). Первый возвращает NIL.

(loop for token in *corpus* do
     (print token))
*corpus*

Я подозреваю, что это связано с чтением из файла как объекта stream, и что (append...) не создает список из этого потока, а вместо этого лениво ждет, пока я не захочу оценить это позже или что-то в этом роде, и в это позднее время он просто решает больше не работать?? (для меня мало смысла).


person GoodQuestions    schedule 03.09.2014    source источник
comment
Ни одна из стандартных функций Common Lisp не является ленивой.   -  person Barmar    schedule 03.09.2014
comment
APPEND не может сказать, и ему все равно, откуда этот список. Список есть список есть список.   -  person Barmar    schedule 03.09.2014
comment
LOOP возвращает NIL, если в нем нет инструкции RETURN <expression> или не используется один из глаголов коллекции. Почему вы ожидаете, что первое выражение что-то вернет? Он распечатает элементы списка как побочный эффект, но не вернет их.   -  person Barmar    schedule 03.09.2014
comment
@Barmar Хм, но я бы подумал, что collect в ключевом слове unless цикла будет означать, что он возвращает список после завершения (когда until доволен)   -  person GoodQuestions    schedule 04.09.2014
comment
Да, TOKENIZE возвращает список. Но в вашем выражении (loop for token...) нет COLLECT, поэтому оно ничего не возвращает.   -  person Barmar    schedule 04.09.2014


Ответы (1)


Это выражение:

(loop for token in *corpus* do
     (print token))

возвращает NIL, поскольку в нем нет предложения RETURN или предложения накопления (например, COLLECT или APPEND). Он просто повторно вызывает PRINT, но отбрасывает возвращаемое значение.

person Barmar    schedule 03.09.2014