Common Lisp case и цитируемые элементы - PullRequest
3 голосов
/ 01 апреля 2011

Я пишу игру для подземелья в CL, и у меня возникают проблемы с формой дела.

Две вещи:

  • Common Lisp жалуется Duplicate keyform QUOTE in CASE statement
  • (make-instance 'cl-rogue:tile tile-type 'wall) должен печататься как "#", но объект печатается как "" независимо от того, какой тип плитки я использую.

код:

(in-package :cl-user)

(defpackage :cl-rogue
  (:use :common-lisp)
  (:export
    :*rows*
    :*cols*
    :*levels*
    :tile
    :tile-type
    :tile-contents
    :tile-hidden
    :tile-locked
    :tile-closed
    :main))

(in-package :cl-rogue)

(defparameter *cols* 80)
(defparameter *rows* 24)
(defparameter *levels* 26)

Класс:

(defclass tile ()
  ((tile-type
    :initarg :tile-type
    :accessor tile-type
    :initform 'floor
    :documentation "Type of tile")
    (tile-contents
      :initarg :tile-contents
      :accessor tile-contents
      :initform '()
      :documentation "Any items the tile holds")
    (tile-hidden
      :initarg :tile-hidden
      :accessor tile-hidden
      :initform nil
      :documentation "Whether the tile is hidden or shown")
    (tile-locked
      :initarg :tile-locked
      :accessor tile-locked
      :initform nil
      :documentation "Whether the tile is locked")
    (tile-closed
      :initarg :tile-closed
      :accessor tile-closed
      :initform nil
      :documentation "Whether the tile is open or closed")))

Способ печати:

(defmethod print-object ((object tile) stream)
  (with-slots (tile-type tile-contents tile-hidden tile-locked tile-closed) object
    (if tile-hidden
      (format stream " ")
      (let ((an-item (car tile-contents)))
        (if an-item
          (format stream "~a" an-item)
          (format stream (case tile-type
            ('wall "#")
            ('upstair "<")
            ('downstair ">")
            ('door (if tile-closed "+" "\\"))
            (otherwise " "))))))))

1 Ответ

11 голосов
/ 01 апреля 2011

Вам не нужно заключать символы в кавычки в CASE.

Символы в предложениях CASE не оцениваются.

(case tile-type
  (wall ...)
  (door ...))

WALL иDOOR являются чисто символами и не оцениваются как переменные.

Читатель Lisp читает 'foo как (quote foo).

Вы писали:

(case tile-type
  ('wall ...)
  ('door ...))

То естьэквивалент:

(case tile-type
  ((quote wall) ...)
  ((quote door) ...))

Но вы не можете заключить в кавычки символ в CASE.Вы должны предоставить символы в виде буквенных констант.

Если вы напишите:

(let ((bar 'foo)
      (baz 'foo))
  (case bar
    (baz :we-have-a-foo-through-baz)
    (foo :we-really-have-a-foo)))

Это вернет :WE-REALLY-HAVE-A-FOO.Поскольку CASE использует постоянные данные, а не переменные.

CASE принимает список элементов.Поскольку у вас есть QUOTE в качестве символа в более чем выражении, компилятор выдает предупреждение.

Как я уже сказал, цитирование невозможно, поскольку элементы не оцениваются.

Какдля CASE принятия списка элементов в пунктах это выглядит следующим образом:

(case tile-type
  ((door wall) ...)
  ((floor window painting) ...))

Для символа WALL необходимо убедиться, что он находится в нужной упаковке при созданииobject.

Лучше использовать символ ключевого слова, например :wall.Тогда вам не нужно экспортировать его, и не возникает путаницы в том, в какой упаковке находится символ.

О форматировании кода : у вас был список с маркерами и сразу после негораздел кода.Это не отображается так, как вы ожидаете.Я добавил текст «Код:» перед кодом.Тогда рендеринг работает как положено.

...