2017-07-02 57 views
0

[SBCL]我想从一个文本文件看起来像这样读取字符逐个字符:Lisp的 - 在DO FORM类型错误时从文件读取

:table 
E E E E E 
E C C C E 
E E E E E 

我的代码(有些省略清晰度):

(defun read-txt (path) 
    (with-open-file str path :direction :input 
        :if-exists :supersede) 
    (let ((a nil) 
      (form read-line str)) 
     (case form 
      (otherwise (do* ((char (read-char str nil) (read-char str nil)) 
          (count 0 (if (char= char #\Newline) (1+ count) count))) 
          ((null char) a))))))) 

给我一个错误,沿着“价值NIL是不是类型字符”。即使在将调试设置为3之后,回溯也没有用处。它告诉我的是,我称之为read-txt,它的参数是一个文件路径。

当我打印文件中的每个字符时,它们都不是NIL。如果我在do的主体中使用char =,我不会收到错误。代码编译时没有错误或警告。

+2

请复制并粘贴所有代码和错误消息。你当前的代码会产生一个不同的错误:'form'的'let'子句被破坏。 – sds

+1

你真的不应该通过手动缩进。编辑应该这样做或Lisp本身。这里的缩进是错误的。 WITH-OPEN-FILE之后的部分参数需要放在括号内。你的代码只有一个右括号,开放的括号是错误的。调整你的代码并重新加载代码 - 但是手动使用工具。缩进非常重要,没有工具就无法可靠地完成缩进。 –

+0

对不起,我不确定如何从emacs的剪贴板粘贴到Firefox。 – plishplop

回答

0

original response

一个do形式的变量列表的末尾形式每次迭代之前评估。该文件中的最后一个字符是nil。由于我在变量列表中呼叫char=,因此在do将被终止之前,nil被传递给它。

Do的身体被评估后的结束形式,这就是为什么一个char=在身体没有造成错误。

2
(defun read-txt (path) 
    (with-open-file str path :direction :input 
    :if-exists :supersede) 
    (let ((a nil) 
     (form read-line str)) 
    (case form 
     (otherwise (do* ((char (read-char str nil) (read-char str nil)) 
         (count 0 (if (char= char #\Newline) (1+ count) count))) 
         ((null char) a)))))) 

这就是你的代码在正确缩进时的样子。

虽然编译此代码SBCL说:

; in: DEFUN READ-TXT 
;  (WITH-OPEN-FILE STR PATH :DIRECTION :INPUT :IF-EXISTS :SUPERSEDE) 
; 
; caught ERROR: 
; during macroexpansion of (WITH-OPEN-FILE STR PATH ...). Use *BREAK-ON-SIGNALS* 
; to intercept. 
; 
; error while parsing arguments to DEFMACRO WITH-OPEN-FILE: 
;  invalid number of elements in 
;  STR 
;  to satisfy lambda list 
;  (STREAM SB-IMPL::FILESPEC &REST SB-IMPL::OPTIONS): 
;  at least 2 expected, but got a non-list 

;  (LET ((A NIL) (FORM READ-LINE STR)) 
;  (CASE FORM 
;   (OTHERWISE 
;   (DO* (# 
;    #) 
;    (# A))))) 
; 
; caught ERROR: 
; The LET binding spec (FORM READ-LINE STR) is malformed. 

;  (SB-INT:NAMED-LAMBDA READ-TXT 
;   (PATH) 
;  (BLOCK READ-TXT 
;   (WITH-OPEN-FILE STR PATH :DIRECTION :INPUT :IF-EXISTS :SUPERSEDE) 
;   (LET ((A NIL) (FORM READ-LINE STR)) 
;   (CASE FORM (OTHERWISE #))))) 
; 
; caught STYLE-WARNING: 
; The variable PATH is defined but never used. 
; 
; compilation unit finished 
; caught 2 ERROR conditions 
; caught 1 STYLE-WARNING condition 

由于代码甚至不编译有几个语法错误,这是很难揣测人能看到什么错误,运行不同的代码时...

但是明确的是:char=需要一个字符。但是在你的循环中它可以得到一个NIL参数,它不是一个字符。如果代码实际上是工作在所有...