Lisp - Type Error bug简单程序

时间:2016-03-11 18:47:14

标签: common-lisp

以下是我在lisp中的代码,我正在使用emacs

(defun eval-var (var state)
  (cond (( atom state) nil)
        ((eql(caar state) var) (cadr (car state)));;(caar state))
        ((eval-var var (cdr state))) ) )

(defvar *clause* '( (not a) (not b) c))

(defvar *state*  '( (a t) (b t) (c t) (d t) ))

(defun eval-clause (clause state)
  (let ((d (cond ((if (equal (car clause) 'a) (eval-var (car clause) state) (not(eval-var (cadr (car clause)) state)))) ))
        (e (cond ((if (equal (cadr clause) 'b) (eval-var (cadr clause) state) (not(eval-var (cadr  (car clause)) state)))) ))
        (f (cond ((if (equal (caddr clause) 'c) (eval-var (caddr clause) state) (not(eval-var (caddr (car clause)) state)))) )) )
    (if (equal d e) t nil )))

下面是我尝试运行这些功能的时候。

* (load "3sat.lisp")

; Loading #P"/Network/Servers/fs.labs.encs/Volumes/raid1/users_a/vetterc7/Desktop/wsu16/cs355/3sat/3sat.lisp".
T
* (eval-clause *clause* *state*)

; Note: Variable F defined but never used.
;
T
* *clause*

((NOT A) (NOT B) C)
* clause

(A (NOT B) C)
* (eval-clause clause *state*)


Type-error in KERNEL::OBJECT-NOT-LIST-ERROR-HANDLER:  A is not of type LIST
   [Condition of type TYPE-ERROR]

Restarts:
  0: [ABORT] Return to Top-Level.

Debug  (type H for help)

(CADR 1 A)[:EXTERNAL]
Source: Error finding source:
Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM:  Source file no longer exists:
  target:code/list.lisp.
0]

我希望有人可以帮助我并解释为什么我会收到此错误以及我需要做些什么来纠正它。

2 个答案:

答案 0 :(得分:3)

如果使用SBCL,您可以看到发生错误的来源。

需要使用更高的调试值编译代码:

(declaim (optimize (debug 3)))

示例:

CL-USER> (eval-clause '(A (NOT B) C) *state*)

debugger invoked on a TYPE-ERROR: The value A is not of type LIST.

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

restarts (invokable by number or by possibly-abbreviated name):
  0: [RETRY            ] Retry SLIME REPL evaluation request.
  1: [ABORT            ] Return to SLIME's top level.
  2: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 12: #<CLOSURE (LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {1004DC423B}>>
  3:                     Exit debugger, returning to top level.
(EVAL-CLAUSE (A (NOT B) C) ((A T) (B T) (C T) (D T)))
   source: (CADR (CAR CLAUSE))

您可以了解来源:

0] source

(CADR (CAR CLAUSE)) 

您无法在符号CAR上致电A

另外一个封闭形式:

0] source 1

(EVAL-VAR (#:***HERE*** (CADR (CAR CLAUSE))) STATE) 

另外两种形式:

0] source 2

(NOT (EVAL-VAR (#:***HERE*** (CADR (CAR CLAUSE))) STATE)) 

0] source 3

(IF (EQUAL (CADR CLAUSE) 'B)
    (EVAL-VAR (CADR CLAUSE) STATE)
    (NOT (EVAL-VAR (#:***HERE*** (CADR (CAR CLAUSE))) STATE))) 

您现在可以在足够的上下文中看到它发生的形式。

答案 1 :(得分:0)

您尝试实现的目标似乎是使用*clause*中的变量评估*state*中的一组逻辑表达式。你当前的代码有点混乱,所以我自己写了一个解决方案,而不是修复它。

我使用名为Optima的库进行模式匹配。您可以在加载以下代码之前运行(ql:quickload :optima),使用quicklisp进行安装。

;; My solution supports NOT, AND and OR operators. AND and OR can only
;; be used with exactly two arguments. These will be evaluated
;; recursively, so they can be nested too.
(defparameter *clause* '((or b c)
                         (not b)
                         (or c (and a b))))

;; I used cons cells here instead of lists. More efficient this way.
;; You can use CAR and CDR to access the parts of a cons cell. Note
;; that accessing the second part is done with just a CDR, rather than
;; with CADR like with lists.
(defparameter *state* '((a . t)
                        (b . t)
                        (c . nil)
                        (d . nil)))

(defun get-var (var state)
  "Get VAR in STATE. Signals an error if VAR doesn't exist."
  ;; You can use ASSOC to find values in an "association list" like
  ;; *STATE*. ASSOC returns the whole cons, so CDR is used to return
  ;; the value of the variable.
  (cdr (or (assoc var state)
           (error "Unknown variable ~a." var))))

(defun eval-clause (clause state)
  "Recursively evaluate CLAUSE using variables in STATE."
  ;; OPTIMA:MATCH performs pattern matching with the first argument
  ;; (CLAUSE in this case). Pattern matching is much like a CASE,
  ;; except it allows you to match against various kinds of patterns
  ;; instead of simple values.
  (optima:match clause
    ;; This matches a single atom (such as A or B) and returns its
    ;; value.
    ((optima:guard var (atom var)) (get-var var state))
    ;; The patterns like `(LIST 'AND a b)` match a list that starts
    ;; with AND and has two elements after it; the two elements will
    ;; be bound to variables A and B, which can then be used in the
    ;; following form.
    ((list 'not a) (not (eval-clause a state)))
    ((list 'and a b) (and (eval-clause a state)
                          (eval-clause b state)))
    ((list 'or a b) (or (eval-clause a state)
                        (eval-clause b state)))
    ;; If CLAUSE doesn't match anything above, signal an error.
    (err-form (error "Unknown expression: ~a." err-form))))

(defun eval-all-clauses (clauses state)
  "Evaluate all logical expressions in CLAUSES using variables in STATE.
Returns a list of results."
  (mapcar (lambda (c) (eval-clause c state)) clauses))

;; Run it
(eval-all-clauses *clause* *state*)
; => (T NIL T)