2010-10-26 76 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)小括號')。如果發現不平衡爲 ,則會發出錯誤信號,並且該點將保留在第一個不平衡的 字符處。