2010-10-26 585 views
6

我正在尝试在Lisp中编写一个数字猜测游戏作为一个耗时的项目。然而,当我尝试加载使用SBCL,我得到以下错误的程序:Common Lisp错误不明白

debugger invoked on a SB-C::INPUT-ERROR-IN-COMPILE-FILE in thread #<THREAD 
                    "initial thread" RUNNING 
                    {AA14959}>: 
    READ failure in COMPILE-FILE at character 477: 
    end of file on #<SB-SYS:FD-STREAM 
        for "file /home/andy/Dropbox/Programming/Common Lisp/number-game.lisp" 
        {B4F45F9}> 

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL. 

restarts (invokable by number or by possibly-abbreviated name): 
    0: [CONTINUE] Ignore runtime option --load "number-game.lisp". 
    1: [ABORT ] Skip rest of --eval and --load options. 
    2:   Skip to toplevel READ/EVAL/PRINT loop. 
    3: [QUIT ] Quit SBCL (calling #'QUIT, killing the process). 

(SB-C::READ-FOR-COMPILE-FILE 
#<SB-SYS:FD-STREAM 
    for "file /home/andy/Dropbox/Programming/Common Lisp/number-game.lisp" 
    {B4F45F9}> 
477) 

这个错误是什么意思?该代码如下,并加载文件,并从REPL调用(play)时出现错误:

;;;; number-game.lisp 
;;;; 
;;;; Andrew Levenson 
;;;; 10/25/2010 
;;;; 
;;;; Simple number guessing game. User has 
;;;; five guesses to determine a number between 
;;;; one and one hundred, inclusive (1-100). 

;;; Set global variable for the target number: 
(defparameter *target* nil) 

;;; Set the iterator so we may check the number of guesses 
(defparameter *number-of-guesses* 0) 

;;; Welcome the user 
(defun welcome-user() 
    (format t "Welcome to the number guessing game!~%")) 

;;; Prompt for a guess 
(defun prompt-for-guess() 
    (format t "Please enter your guess (1-100): ") 
    (finish-output nil) ; nil directs finish-output to standard IO 
    (check-guess((read-guess))) 

;;; Read in a guess 
(defun read-guess() 
    (let ((guess (read))) 
     (if (numberp guess) ; If true, return guess. Else, call prompt-for-guess 
      (progn 
       (setq *number-of-guesses* (+ *number-of-guesses* 1)) 
       guess) 
      (prompt-for-guess)))) 

;;; Check if the guess is higher than, lower than, or equal to, the target 
(defun check-guess (guess) 
    (if (equal guess *target*) 
     (equal-to) 
     (if (> guess *target*) 
      (greater-than (guess)) 
      (if (< guess *target*) 
       (less-than (guess)))))) 

;;; If the guess is equal to the target, the game is over 
(defun equal-to() 
    (format t "Congratulations! You have guessed the target number, ~a!~%" *target*) 
    (y-or-n-p "Play again? [y/n] ")) 

;;; If the guess is greater than the target, inform the player. 
(defun greater-than (guess) 
    (format t "Sorry, ~a is greater than the target.~%" guess) 
    (if (< *number-of-guesses* 6) 
     (prompt-for-guess) 
     (game-over))) 

;;; If the guess is less than the target, inform the player. 
(defun less-than (guess) 
    (format t "Sorry, ~a is less than the target.~%" guess) 
    (if (< *number-of-guesses* 6) 
     (prompt-for-guess) 
     (game-over))) 

;;; If the player has run out of guesses, give them the option 
;;; of playing the game again. 
(defun game-over() 
    (y-or-n-p "You have run out of guesses. Play again? [y/n] ")) 


;;; Play the game 
(defun play() 
    ;; If it's their first time playing this session, 
    ;; make sure to greet the user. 
    (unless (> *number-of-guesses* 0) 
     (welcome-user)) 
    ;; Reset their remaining guesses 
    (setq *number-of-guesses* 0) 
    ;; Set the target value 
    (setq *target* 
     ;; Random can return float values, 
     ;; so we must round the result to get 
     ;; an integer value. 
     (round 
      ;; Add one to the result, because 
      ;; (random 100) yields a number between 
      ;; 0 and 99, whereas we want a number 
      ;; from 1 to 100 inclusive. 
      (+ (random 100) 1))) 
    (if (equal (prompt-for-guess) "y") 
     (play) 
     (quit))) 

(我相当肯定的是,程序不能正常工作减去一个错误,我仍然这是我遇到的第一个我自己无法想象的错误)

噢,这个问题最有可能与prompt-for-guess,read-guesscheck-guess的功能,因为那些是我在这个错误出现时搞乱了。

回答

6

它看起来像你没有关闭你的defun足够的parens。

读者正在接近文件的末尾,并注意到它仍然有一个窗体打开,并且无法确定它来自哪里。

一个简单的方法,我用这种方法找到这样的错误是让我的文本编辑器缩进区域,并确保所有东西都像我认为应该的那样排列。

+0

太棒了,修正了那个错误!谢谢!现在我需要弄清楚如何将函数的返回值作为参数传递给另一个函数。 :) – Andy 2010-10-26 18:19:27

+2

@Andrew:'(其他功能(第一功能))'? – 2010-10-26 22:45:54

1

文件结尾期间读取,有一个右括号(或类似)丢失。字符477.将文本中的光标移动到477并检查它是哪个表达式。

检查您的IDE以找到不平衡表达式的命令。

在LispWorks中这将是M-x找到不平衡圆括号

SLIME也应该有一些命令。

3

Emacs中的命令是M-x check-parens(它检查所有需要平衡的内容,例如引号)。如果一切均衡,可能会有点神秘,因为在这种情况下它什么都不做。

check-parens 命令:检查当前缓冲区中不平衡的括号。 更准确地说,一般来说,请检查缓冲区的缩小部分是否有不平衡的 表达式(“sexps”)。这是根据 当前语法表完成的,并且会发现不平衡的括号或引号为 合适。 (请参阅信息节点(emacs)小括号')。如果发现不平衡为 ,则会发出错误信号,并且该点将保留在第一个不平衡的 字符处。