Распространенная ошибка Lisp: ожидаемый тип: REAL данные: NIL

На этот раз я работаю над написанием чего-нибудь на Common Lisp самостоятельно, реализуя алгоритм маневрового двора. Я думал, что все прошло нормально, даже если получилось довольно некрасиво, и если я сомневаюсь в его лисповидности, но после тестирования функции в REPL я получил ошибку в заголовке.

Код выглядит следующим образом, а тестовый пример - (shunting-yard '(3 + 5)).

(defparameter *output-queue*   nil)
(defparameter *operator-stack* nil)

(defun determine-precedence (operator)
  (case operator
    (('+ '-) 2)
    (('* '/) 3)
    ('^      4)))

(defun shunting-yard (stmt)
  (loop until (null stmt) do
       (let ((token (car stmt)))
         (cond ((or (numberp token)
            (eq token '\())
            (setf *output-queue* (cons token *output-queue*)))
               ((mapcar #'(lambda (x) (eq token x)) '(+ - * / ^))
            (let* ((token-precedence (determine-precedence token))
                   (stack-topmost (car *operator-stack*))
                   (stack-precedence (determine-precedence stack-topmost)))
              (when (< token-precedence stack-precedence)
                (setf *output-queue* (cons stack-topmost *output-queue*))
                (setf *operator-stack* (cdr *operator-stack*)))
              (setf *operator-stack* (cons token *operator-stack*))))
               ((eq token '\))
            (loop for stack-topmost in *operator-stack*
               until (eq stack-topmost '\()
               do (progn
                (setf *output-queue* (cons stack-topmost *output-queue*))
                (setf *operator-stack* (cdr *operator-stack*)))
               finally (setf *operator-stack* (cdr *operator-stack*)))))
         (setf stmt (cdr stmt))))
  (loop while (not (null *operator-stack*))
     do (progn
      (setf *output-queue* (cons (car *operator-stack*) *output-queue*))
      (setf *operator-stack* (cdr *operator-stack*))))
  (nreverse *output-queue*))

Ошибка в самом коде (я предполагаю) или в моем тестовом примере?

Заранее большое спасибо, это было ДЕЙСТВИТЕЛЬНО весело писать, и я не могу дождаться, чтобы поработать над чем-то еще, но только после того, как у меня это заработает.


person Oso    schedule 02.03.2011    source источник


Ответы (1)


Есть несколько ошибок:

Первый:

(defun determine-precedence (operator)
  (case operator
    (('+ '-) 2)
    (('* '/) 3)
    ('^      4)))

Котировки нужно оставить. Все.

Второй:

(mapcar #'(lambda (x) (eq token x)) '(+ - * / ^))

Выше не делаешь то, что думаешь. Замените его вызовом MEMBER.

В третьих:

 (when (< token-precedence stack-precedence)

Вам нужно убедиться, что переменные действительно привязаны к числам. Используйте что-то вроде

 (check-type token-precedence number)
 (check-type stack-precedence number)

раньше как проверка.

Удачной дальнейшей отладки ...

person Rainer Joswig    schedule 02.03.2011
comment
Большое спасибо за Вашу помощь! Хотя есть один вопрос. Почему (mapcar #'(lambda (x) (eq token x) '(+ - * / ^)) не подходит для моей цели? Я думал, что любое значение, отличное от нуля, считается истиной. - person Oso; 02.03.2011
comment
@ Андрей: что возвращает ваш MAPCAR? Непустой список. Такой список всегда верен. Ваша конструкция никогда не будет NIL. - person Rainer Joswig; 02.03.2011
comment
Оххх. mapcan было бы лучше, или у меня серьезное недоразумение? (Скорее всего, последнее) - person Oso; 02.03.2011