【问题标题】:Common Lisp reading from file and storing as listCommon Lisp 从文件中读取并存储为列表
【发布时间】:2014-09-03 19:12:54
【问题描述】:

所以做了一些常见的 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 个应该都有效的表达式,但只有后者有效(corpus 一个)。第一个返回 NIL。

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

我怀疑它与从文件作为 stream 对象读取有关,并且 (append ...) 不会从该流创建列表,而是懒惰等待直到 i想稍后评估或总结,然后它就决定不再工作了? (对我来说毫无意义)。

【问题讨论】:

  • 没有一个标准的 Common Lisp 函数是惰性的。
  • APPEND 不知道也不关心列表的来源。列表就是列表。
  • LOOP 返回NIL,除非它有RETURN <expression> 语句或使用集合动词之一。为什么你期望第一个表达式返回一些东西?它将打印列表元素作为副作用,但不返回它们。
  • @Barmar 嗯,但我原以为循环的 unless 关键字上的 collect 意味着它在完成后返回一个列表(当直到满足时)
  • 是的,TOKENIZE 返回一个列表。但是您的 (loop for token...) 表达式中没有 COLLECT,因此它不会返回任何内容。

标签: common-lisp sbcl


【解决方案1】:

这个表达式:

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

返回NIL,因为它没有RETURN 子句或累积子句(例如COLLECTAPPEND)。它只是重复调用PRINT,但丢弃它的返回值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多